Skip to content

A custom Doctrine type that maps column values to enum objects using myclabs/php-enum

License

Notifications You must be signed in to change notification settings

hdimo/doctrine-enum-type

 
 

Repository files navigation

Doctrine Enum Type

Build Status Code Coverage Scrutinizer Code Quality PHPStan Latest Stable Version Total Downloads License

This package provides a base implementation to define doctrine entity column types that are mapped to MyCLabs\Enum\Enum objects. That class is defined in the fantastic myclabs/php-enum package.

Installation

Install this package using composer by running composer require acelaya/doctrine-enum-type.

Usage

This package provides a Acelaya\Doctrine\Type\PhpEnumType class that extends Doctrine\DBAL\Types\Type. You can use it to easily map type names to concrete Enums.

The PhpEnumType class will be used as the doctrine type for every property that is an enumeration.

Let's imagine we have this two enums.

<?php
namespace Acelaya\Enum;

use MyCLabs\Enum\Enum;

class Action extends Enum
{
    const CREATE    = 'create';
    const READ      = 'read';
    const UPDATE    = 'update';
    const DELETE    = 'delete';
}
<?php
namespace Acelaya\Enum;

use MyCLabs\Enum\Enum;

class Gender extends Enum
{
    const MALE      = 'male';
    const FEMALE    = 'female';
}

And this entity, with a column of each entity type.

<?php
namespace Acelaya\Entity;

use Acelaya\Enum\Action;
use Acelaya\Enum\Gender;
use Doctrine\ORM\Mapping as ORM;

/**
 * @ORM\Entity()
 * @ORM\Table(name="users")
 */
class User
{
    /**
     * @var int
     *
     * @ORM\Id
     * @ORM\Column(type="integer")
     * @ORM\GeneratedValue(strategy="AUTO")
     */
    protected $id;
    /**
     * @var string
     *
     * @ORM\Column()
     */
    protected $name;
    /**
     * @var Action
     *
     * @ORM\Column(type=Action::class)
     */
    protected $action;
    /**
     * @var Gender
     *
     * @ORM\Column(type="php_enum_gender")
     */
    protected $gender;

    // Getters and setters...
}

The column type of the action property is the FQCN of the Action enum, and the gender column type is php_enum_gender. To get this working, you have to register the concrete column types, using the Acelaya\Doctrine\Type\PhpEnumType::registerEnumType static method.

<?php
// in bootstrapping code

// ...

use Acelaya\Doctrine\Type\PhpEnumType;
use Acelaya\Enum\Action;
use Acelaya\Enum\Gender;

// ...

// Register my types
PhpEnumType::registerEnumType(Action::class);
PhpEnumType::registerEnumType('php_enum_gender', Gender::class);

That will internally register a customized doctrine type. As you can see, it its possible to just pass the FQCN of the enum, making the type use it as the name, but you can also provide a different name.

Alternatively you can use the Acelaya\Doctrine\Type\PhpEnumType::registerEnumTypes, which expects an array of enums to register.

<?php
// ...

use Acelaya\Doctrine\Type\PhpEnumType;
use Acelaya\Enum\Action;
use Acelaya\Enum\Gender;

PhpEnumType::registerEnumTypes([
    Action::class,
    'php_enum_gender' => Gender::class,
]);

With this method, elements with a string key will be registered with that name, and elements with integer key will use the value as the type name.

Do the same for each concrete enum you want to register.

If you need more information on custom doctrine column types, read this http://doctrine-orm.readthedocs.io/en/latest/cookbook/custom-mapping-types.html

Customize SQL declaration

By default, the Acelaya\Doctrine\Type\PhpEnumType class defines all enums as as a VARCHAR(255) like this:

public function getSQLDeclaration(array $fieldDeclaration, AbstractPlatform $platform)
{
    return $platform->getVarcharTypeDeclarationSQL([]);
}

If you want something more specific, like a MySQL enum, just extend PhpEnumType and overwrite the getSQLDeclaration() method with something like this.

namespace App\Type;

use Acelaya\Doctrine\Type\PhpEnumType;

class MyPhpEnumType extends PhpEnumType
{
    public function getSQLDeclaration(array $fieldDeclaration, AbstractPlatform $platform)
    {
        $values = call_user_func([$this->enumClass, 'toArray']);
        return sprintf(
            'ENUM("%s") COMMENT "%s"',
            implode('", "', $values),
            $this->getName()
        );
    }
}

Then remember to register the enums with your own class.

<?php
// ...

use Acelaya\Enum\Action;
use Acelaya\Enum\Gender;
use App\Type\MyPhpEnumType;

MyPhpEnumType::registerEnumTypes([
    Action::class,
    'php_enum_gender' => Gender::class,
]);

About

A custom Doctrine type that maps column values to enum objects using myclabs/php-enum

Resources

License

Stars

Watchers

Forks

Packages

No packages published

Languages

  • PHP 100.0%