Skip to content

Commit 3990783

Browse files
author
Gusarov
committed
initial commit. hope no bugs
1 parent 269c8af commit 3990783

File tree

9 files changed

+547
-6
lines changed

9 files changed

+547
-6
lines changed

.gitignore

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
1-
composer.phar
1+
.idea/
2+
.vscode/
3+
/coverage/
24
/vendor/
3-
4-
# Commit your application's lock file https://getcomposer.org/doc/01-basic-usage.md#commit-your-composer-lock-file-to-version-control
5-
# You may choose to ignore a library lock file http://getcomposer.org/doc/02-libraries.md#lock-file
6-
# composer.lock
5+
.phpunit.result.cache
6+
composer.lock

README.md

Lines changed: 92 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1,92 @@
1-
# php-enum-doctrine
1+
# Php Enum doctrine
2+
3+
* Allows to add you custom php enums as doctrine type.
4+
* Supports generation of correct alter SQL when updating enum values.
5+
6+
Extension for [php-enum](https://github.com/gusarov112/php-enum) (myclabs fork)
7+
8+
## Installation
9+
10+
Add github repository to composer.json
11+
```json
12+
{
13+
"repositories": [
14+
{
15+
"type": "vcs",
16+
"url": "[email protected]:gusarov112/php-enum-doctrine.git"
17+
}
18+
]
19+
}
20+
```
21+
Than require package
22+
```bash
23+
composer require gusarov112/php-enum-doctrine
24+
```
25+
26+
## Symfony configuration
27+
```
28+
Gusarov112\PhpEnumDoctrine\EventListener\EnumUpdaterSubscriber:
29+
tags:
30+
- { name: doctrine.event_subscriber }
31+
```
32+
33+
## Example
34+
35+
### Create enum
36+
```php
37+
class PetEnum extends \Gusarov112\Enum\Enum
38+
{
39+
const CAT = 'CAT';
40+
const DOG = 'DOG';
41+
}
42+
```
43+
### Create corresponding enum type by extending abstract type
44+
```php
45+
class PetType extends \Gusarov112\PhpEnumDoctrine\DBAL\EnumType
46+
{
47+
public function getEnumClassName(): string
48+
{
49+
return PetEnum::class;
50+
}
51+
52+
public function getName()
53+
{
54+
return 'pet_type';
55+
}
56+
}
57+
```
58+
### Use your column type in doctrine entity
59+
```php
60+
use Doctrine\ORM\Mapping as ORM;
61+
62+
class PetEntity {
63+
/**
64+
* @var PetEnum
65+
* @ORM\Column(type="pet_type")
66+
*/
67+
private $type;
68+
69+
public function getType(): PetEnum
70+
{
71+
return $this->type;
72+
}
73+
74+
public function setType(PetEnum $type): self
75+
{
76+
$this->type = $type;
77+
78+
return $this;
79+
}
80+
}
81+
```
82+
### Do not forger to register your type
83+
```php
84+
\Doctrine\DBAL\Types\Type::addType('pet_type', PetType::class);
85+
```
86+
### Add event subscriber if you have migrations bundle and want to autogenerate enum list alter SQL's
87+
```php
88+
$eventManager = new \Doctrine\Common\EventManager();
89+
$eventManager->addEventSubscriber(new \Gusarov112\PhpEnumDoctrine\EventListener\EnumUpdaterSubscriber());
90+
91+
#!/bin/bash ./vendor/bin/doctrine migrations:diff
92+
```

composer.json

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
{
2+
"name": "gusarov112/php-enum-doctrine",
3+
"description": "Allows to add you custom php enums as doctrine type",
4+
"keywords": [
5+
"generic",
6+
"collection"
7+
],
8+
"homepage": "http://github.com/gusarov112/php-enum-doctrine",
9+
"license": "MIT",
10+
"authors": [
11+
{
12+
"name": "Anatolii Husarov",
13+
"email": "[email protected]"
14+
}
15+
],
16+
"repositories":[
17+
{
18+
"type": "vcs",
19+
"url": "[email protected]:gusarov112/php-enum.git"
20+
}
21+
],
22+
"require": {
23+
"php": "^7.1",
24+
"ext-json": "*",
25+
"ext-pdo": "*",
26+
"gusarov112/php-enum": "v1.0.0",
27+
"doctrine/orm": "^2.7"
28+
},
29+
"autoload": {
30+
"psr-4": {
31+
"Gusarov112\\PhpEnumDoctrine\\": "src/"
32+
}
33+
}
34+
}

doc.php

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
<?php
2+
declare(strict_types=1);
3+
4+
class PetEnum extends \Gusarov112\Enum\Enum
5+
{
6+
const CAT = 'CAT';
7+
const DOG = 'DOG';
8+
}
9+
10+
class PetType extends \Gusarov112\PhpEnumDoctrine\DBAL\EnumType
11+
{
12+
public function getEnumClassName(): string
13+
{
14+
return PetEnum::class;
15+
}
16+
17+
public function getName()
18+
{
19+
return 'pet_type';
20+
}
21+
}
22+
23+
use Doctrine\ORM\Mapping as ORM;
24+
25+
class PetEntity {
26+
/**
27+
* @var PetEnum
28+
* @ORM\Column(type="pet_type")
29+
*/
30+
private $type;
31+
32+
public function getType(): PetEnum
33+
{
34+
return $this->type;
35+
}
36+
37+
public function setType(PetEnum $type): self
38+
{
39+
$this->type = $type;
40+
41+
return $this;
42+
}
43+
}
44+
45+
\Doctrine\DBAL\Types\Type::addType('pet_type', PetType::class);
46+
47+
$eventManager = new \Doctrine\Common\EventManager();
48+
$eventManager->addEventSubscriber(new \Gusarov112\PhpEnumDoctrine\EventListener\EnumUpdaterSubscriber());
49+
#!/bin/bash ./vendor/bin/doctrine migrations:diff
50+
51+

src/DBAL/EnumType.php

Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
<?php
2+
declare(strict_types=1);
3+
4+
namespace Gusarov112\PhpEnumDoctrine\DBAL;
5+
6+
use Doctrine\DBAL\Platforms\AbstractPlatform;
7+
use Doctrine\DBAL\Types\ConversionException;
8+
use Doctrine\DBAL\Types\Type;
9+
use Exception;
10+
use Gusarov112\Enum\Enum;
11+
12+
/**
13+
* @package WL\CommonBundle\DBAL\Type
14+
*/
15+
abstract class EnumType extends Type
16+
{
17+
/**
18+
* @return string Enum class name
19+
*/
20+
abstract public function getEnumClassName(): string;
21+
22+
/**
23+
* Gets the SQL declaration snippet for a field of this type.
24+
*
25+
* @param array $fieldDeclaration The field declaration.
26+
* @param AbstractPlatform $platform The currently used database platform.
27+
*
28+
* @return string
29+
*/
30+
public function getSQLDeclaration(array $fieldDeclaration, AbstractPlatform $platform)
31+
{
32+
/** @var Enum $enumClass */
33+
$enumClass = $this->getEnumClassName();
34+
$phpEnumValues = array_values($enumClass::toArray());
35+
$currentDbEnumValues = $fieldDeclaration['currentDbEnumValues'] ?? [];
36+
$resultEnumValues = array_merge($currentDbEnumValues, array_diff($phpEnumValues, $currentDbEnumValues));
37+
38+
return sprintf('ENUM(%s)', '"'.implode('","', $resultEnumValues).'"');
39+
}
40+
41+
/**
42+
* @param Enum $value
43+
* @param AbstractPlatform $platform
44+
* @return mixed
45+
*/
46+
public function convertToDatabaseValue($value, AbstractPlatform $platform)
47+
{
48+
return is_null($value) ? null : $value->getValue();
49+
}
50+
51+
/**
52+
* @param mixed $value
53+
* @param AbstractPlatform $platform
54+
* @return Enum
55+
* @throws ConversionException
56+
*/
57+
public function convertToPHPValue($value, AbstractPlatform $platform)
58+
{
59+
$result = null;
60+
if (!is_null($value)) {
61+
$className = $this->getEnumClassName();
62+
try {
63+
$result = new $className($this->castEnumValue($value));
64+
} catch (Exception $e) {
65+
throw new ConversionException($e->getMessage(), $e->getCode(), $e);
66+
}
67+
}
68+
69+
return $result;
70+
}
71+
72+
public function requiresSQLCommentHint(AbstractPlatform $platform)
73+
{
74+
return true;
75+
}
76+
77+
protected function castEnumValue($value)
78+
{
79+
return (string)$value;
80+
}
81+
}
Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
<?php
2+
declare(strict_types=1);
3+
4+
namespace Gusarov112\PhpEnumDoctrine\DBAL\Schema;
5+
6+
use Doctrine\DBAL\Event\SchemaAlterTableAddColumnEventArgs;
7+
use Doctrine\DBAL\Event\SchemaAlterTableChangeColumnEventArgs;
8+
use Doctrine\DBAL\Event\SchemaCreateTableColumnEventArgs;
9+
use Doctrine\DBAL\Schema\Column;
10+
use Doctrine\DBAL\Schema\Table;
11+
use Doctrine\ORM\Tools\Event\GenerateSchemaEventArgs;
12+
use Gusarov112\Enum\Enum;
13+
use Gusarov112\PhpEnumDoctrine\DBAL\EnumType;
14+
use PDO;
15+
16+
class MysqlEnumUpdater implements PlatformEventEnumValueUpdaterInterface
17+
{
18+
public function getPlatformName(): string
19+
{
20+
return 'mysql';
21+
}
22+
23+
public function postGenerateSchema(GenerateSchemaEventArgs $eventArgs, Table $table, Column $column)
24+
{
25+
/** @var EnumType $type */
26+
$type = $column->getType();
27+
/** @var Enum $enumClassName */
28+
$enumClassName = $type->getEnumClassName();
29+
30+
$query = $eventArgs->getEntityManager()
31+
->getConnection()
32+
->createQueryBuilder()
33+
->select('column_type')
34+
->from('information_schema.COLUMNS')
35+
->where('TABLE_NAME = :table AND COLUMN_NAME = :column')
36+
->setParameters(
37+
[
38+
'table' => $table->getName(),
39+
'column' => $column->getName(),
40+
]
41+
)
42+
;
43+
$statement = $query->execute();
44+
$result = $statement->fetch(PDO::FETCH_NUM);
45+
if (false !== $result) {
46+
$columnType = $result[0];
47+
$dbEnum = preg_replace('/^enum\(|\)$/i', '', $columnType);
48+
$currentDbEnumValues = array_map(
49+
function ($value) {
50+
return trim($value, '\'"');
51+
},
52+
explode(',', $dbEnum)
53+
);
54+
$phpEnumValues = array_values($enumClassName::toArray());
55+
if (!empty(array_diff($phpEnumValues, $currentDbEnumValues))) {
56+
$resultEnumValues = array_merge($currentDbEnumValues, array_diff($phpEnumValues, $currentDbEnumValues));
57+
$enumTypeDeclaration = sprintf('ENUM(%s)', '"'.implode('","', $resultEnumValues).'"');
58+
$column->setCustomSchemaOption('enumTypeDeclaration', $enumTypeDeclaration);
59+
}
60+
}
61+
}
62+
63+
public function onSchemaCreateTableColumn(SchemaCreateTableColumnEventArgs $eventArgs)
64+
{
65+
}
66+
67+
public function onSchemaAlterTableChangeColumn(SchemaAlterTableChangeColumnEventArgs $eventArgs)
68+
{
69+
}
70+
71+
public function onSchemaAlterTableAddColumn(SchemaAlterTableAddColumnEventArgs $eventArgs)
72+
{
73+
}
74+
}
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
<?php
2+
declare(strict_types=1);
3+
4+
namespace Gusarov112\PhpEnumDoctrine\DBAL\Schema;
5+
6+
use Doctrine\DBAL\Event\SchemaAlterTableAddColumnEventArgs;
7+
use Doctrine\DBAL\Event\SchemaAlterTableChangeColumnEventArgs;
8+
use Doctrine\DBAL\Event\SchemaCreateTableColumnEventArgs;
9+
use Doctrine\DBAL\Schema\Column;
10+
use Doctrine\DBAL\Schema\Table;
11+
use Doctrine\ORM\Tools\Event\GenerateSchemaEventArgs;
12+
13+
interface PlatformEventEnumValueUpdaterInterface
14+
{
15+
public function getPlatformName(): string;
16+
17+
public function postGenerateSchema(GenerateSchemaEventArgs $eventArgs, Table $table, Column $column);
18+
19+
public function onSchemaCreateTableColumn(SchemaCreateTableColumnEventArgs $eventArgs);
20+
21+
public function onSchemaAlterTableChangeColumn(SchemaAlterTableChangeColumnEventArgs $eventArgs);
22+
23+
public function onSchemaAlterTableAddColumn(SchemaAlterTableAddColumnEventArgs $eventArgs);
24+
}

0 commit comments

Comments
 (0)