Developed with love by KnpLabs Hire us for your project!
190

DoctrineEnumBundle

by fre5h

Provides support of ENUM type for Doctrine in Symfony applications.

DoctrineEnumBundle

Provides support of ENUM type for Doctrine in Symfony applications.

Scrutinizer Quality Score
Build Status
CodeCov
License
Latest Stable Version
Total Downloads
Dependency Status
SensioLabsInsight
Gitter

knpbundles.com

Supported platforms

  • MySQL
  • SQLite
  • PostgreSQL

Requirements

  • PHP 5.4 and later
  • Symfony 2.5 and later
  • Doctrine 2.2 and later

Installation

Install via Composer

php composer.phar require fresh/doctrine-enum-bundle='v3.2'

Register the bundle

To start using the bundle, register it in app/AppKernel.php:

public function registerBundles()
{
    $bundles = [
        // Other bundles...
        new Fresh\DoctrineEnumBundle\FreshDoctrineEnumBundle(),
    ];
}

Update config.yml

Add the following lines for doctrine configuration in config.yml file:

# Doctrine Configuration
doctrine:
    dbal:
        mapping_types:
            enum: string

Using

Example

In this example will be shown how to create custom ENUM field for basketball positions. This ENUM should contain five values:

  • PG - Point guard
  • SG - Shooting guard
  • SF - Small forward
  • PF - Power forward
  • C - Center

Create class for new ENUM type BasketballPositionType:

<?php
namespace AppBundle\DBAL\Types;

use Fresh\DoctrineEnumBundle\DBAL\Types\AbstractEnumType;

class BasketballPositionType extends AbstractEnumType
{
    const POINT_GUARD    = 'PG';
    const SHOOTING_GUARD = 'SG';
    const SMALL_FORWARD  = 'SF';
    const POWER_FORWARD  = 'PF';
    const CENTER         = 'C';

    protected static $choices = [
        self::POINT_GUARD    => 'Point guard',
        self::SHOOTING_GUARD => 'Shooting guard',
        self::SMALL_FORWARD  => 'Small forward',
        self::POWER_FORWARD  => 'Power forward',
        self::CENTER         => 'Center'
    ];
}

Register BasketballPositionType for Doctrine in config.yml:

# Doctrine Configuration
doctrine:
    dbal:
        types:
            BasketballPositionType: AppBundle\DBAL\Types\BasketballPositionType

Create Player entity that has position field:

<?php
namespace AppBundle\Entity;

use AppBundle\DBAL\Types\BasketballPositionType;
use Doctrine\ORM\Mapping as ORM;
use Fresh\DoctrineEnumBundle\Validator\Constraints as DoctrineAssert;

/**
 * @ORM\Entity()
 * @ORM\Table(name="players")
 */
class Player
{
    /**
     * @ORM\Id
     * @ORM\Column(name="id", type="integer")
     * @ORM\GeneratedValue(strategy="AUTO")
     */
    protected $id;

    /**
     * @DoctrineAssert\Enum(entity="AppBundle\DBAL\Types\BasketballPositionType")
     * @ORM\Column(name="position", type="BasketballPositionType", nullable=false)
     */
    protected $position;

    public function getId()
    {
        return $this->id;
    }

    public function setPosition($position)
    {
        $this->position = $position;
    }

    public function getPosition()
    {
        return $this->position;
    }
}

Now you can set a position for Player inside some action or somewhere else:

$player->setPosition(BasketballPositionType::POINT_GUARD);

But don't forget to define BasketballPositionType in the use section:

use AppBundle\DBAL\Types\BasketballPositionType;

NULL values are also supported by ENUM field.
You can set nullable parameter of column to true or false depends on if you want or not to allow NULL values:

/** @ORM\Column(name="position", type="BasketballPositionType", nullable=true) */
protected $position;
// or
/** @ORM\Column(name="position", type="BasketballPositionType", nullable=false) */
protected $position;
Building the form

When build BasketballPositionType as form field, you don't need to specify some additional parameters. Just add property to the form builder and EnumTypeGuesser will do all work for you. That's how:

$builder->add('position');

If you need to add some extra parameters, just skip the second (field type) parameter:

$builder->add('position', null, [
    'required' => true,
    'attr'     => [
        'class' => 'some-class'
    ]
]);

If for some reason you need to specify full config, it can look like this:
php
$builder->add('position', 'choice', [
'choices' => BasketballPositionType::getChoices()
]);

EnumTypeGuesser process only DBAL types that are children of AbstractEnumType.
All other custom DBAL types, which are defined, will be skipped from guessing.

Additional methods

AbstractEnumType provides few additional methods, which might be useful.

If you need to check if some string value exists in the array of ENUM values:

BasketballPositionType::isValueExist('Pitcher'); // false

If you need to get value in readable format:

BasketballPositionType::getReadableValue(BasketballPositionType::SHOOTING_GUARD);
// Will output: Shooting guard
Readable ENUM values in templates

You would want to show ENUM values rendered in your templates in readable format instead of the values that would be stored in DB. It is easy to do by using the Twig filter |readable that was implemented for that purpose. In the example below if the player is a point guard of his team then his position will be rendered in template as Point guard instead of PG.

{{ player.position|readable }}

How it works? If there is no additional parameter for the filter, ReadableEnumValueExtension tries to find which ENUM type of the registered ENUM types consists this value. If only one ENUM type found, then it is possible to get the readable value from it. Otherwise it will throw an exception.

For example BasketballPositionType and MapLocationType can have same ENUM value C with its readable variant Center. The code below will throw an exception, because without additional parameter for |readable filter, it can't determine which ENUM type to use in which case:

{{ set player_position = 'C' }}
{{ set location_on_the_map = 'C' }}

{{ player_position|readable }}
{{ location_on_the_map|readable }}

So, that correct usage of |readable filter in this case should be with additional parameter that specifies the ENUM type:

{{ set player_position = 'C' }}
{{ set location_on_the_map = 'C' }}

{{ player_position|readable('BasketballPositionType') }}
{{ location_on_the_map|readable('MapLocationType') }}

Hook for Doctrine migrations

If you use Doctrine migrations in your project you should be able to create migrations for you custom ENUM types. If you want to create migration for the new ENUM type, then just use console commands doctrine:migrations:diff to create migration and doctrine:migrations:migrate to execute it.

For the previous example of BasketballPositionType for MySQL DB (e.g.) Doctrine will generate SQL statement, that looks like this:

CREATE TABLE players (
    id INT AUTO_INCREMENT NOT NULL,
    position ENUM('PG', 'SG', 'SF', 'PF', 'C') NOT NULL COMMENT '(DC2Type:BasketballPositionType)',
    PRIMARY KEY(id)
) DEFAULT CHARACTER SET utf8 COLLATE utf8_unicode_ci ENGINE = InnoDB

You can see here the comment '(DC2Type:BasketballPositionType)' for position column. Doctrine will know that this column should be processed as BasketballPositionType.

If you later will need to add new values to ENUM or delete some existed, you also will need to create new migrations. But Doctrine won't detect any changes in your ENUM... :(

Fortunately you can do simple hook =) Access your database and delete comment for position column. After that run console command doctrine:migrations:diff it will create correct migrations.

You should repeat these steps after each update of your custom ENUM type!

The MIT License (MIT)

Copyright (c) 2012-2015 Artem Genvald

Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
the Software, and to permit persons to whom the Software is furnished to do so,
subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  • Merge pull request #26 from stevepeak/patch-1
    By fre5h, 1 year ago
  • update Codecov method coverage
    By , 1 year ago
  • Update README. Remove Acme namespace
    By fre5h, 1 year ago
  • Simplify Scrutinizer config
    By fre5h, 1 year ago
  • Update README.md
    By fre5h, 1 year ago
  • Add more tests
    By fre5h, 1 year ago
  • Add FreshDoctrineEnumExtensionTest
    By fre5h, 1 year ago
  • Add some tests
    By fre5h, 1 year ago
  • Update Scrutinizer config
    By fre5h, 1 year ago
  • Update version in README and exclude vendors in PhpUnit suite
    By fre5h, 1 year ago
  • Merge pull request #23 from fre5h/featue-postgresql-integration
    By fre5h, 1 year ago
  • Add support for PostgreSQL
    By fre5h, 1 year ago
  • Merge pull request #21 from fre5h/feature-update-docs
    By fre5h, 1 year ago
  • Add description about additional methods
    By fre5h, 1 year ago
  • Add CodeCov confing and badge
    By fre5h, 2 years ago
  • Update badges and clear docs
    By fre5h, 2 years ago
  • Replace is_null($value) with null === $value
    By fre5h, 2 years ago
  • Update year in license
    By fre5h, 2 years ago
  • Merge pull request #19 from fre5h/fix-required-entity-option
    By fre5h, 2 years ago
  • Update README and composer.json
    By fre5h, 2 years ago
  • Fix required entity option. Small CS fix and refactoring
    By fre5h, 2 years ago
  • Merge pull request #18 from fre5h/3.0
    By fre5h, 2 years ago
  • Merge remote-tracking branch 'remotes/origin/master' into 3.0
    By fre5h, 2 years ago
  • Refactoring
    By fre5h, 2 years ago
  • Update README.md
    By fre5h, 2 years ago
  • Update composer.json
    By fre5h, 2 years ago
  • Update badges
    By fre5h, 2 years ago
  • Add reference badge
    By fre5h, 2 years ago
  • Remove BitDeli badge. It doesn't work anymore :(
    By fre5h, 2 years ago
  • Update .travis.yml
    By fre5h, 2 years ago