Using Enum in a Symfony App isn’t obvious. If your Enum is short, you can directly put it on your entity. But if it grows, it will be quickly unmanageable.

The problem

Ok given, you want to create an Message object which contain an attribute called type. Like Twitter Bootstrap’s Alert, your Message type’s attribute must contain some specific strings (e.g. info, success…).

In the official documentation, Doctrine provide 2 solutions for MySQL Database. What happen if we want to use another Database like PostgreSQL? By the way, you can also take a look at these solutions. As far as i am concerned, I don’t like them because it didn’t solve the problem on the PHP side.

Obviously, we can also create a Table called MessageType. But according to me, a database table must be used to store data. In this case, a type isn’t managed by a human.

So we need custom reusable PHP Enum.
Let’s do this!

A solution

First, you need to create a MessageTypeEnum.

<?php

namespace DemoBundle\Enum;

abstract class MessageTypeEnum
{
    const TYPE_INFO    = "info";
    const TYPE_WARNING = "warning";
    const TYPE_SUCCESS = "success";
    const TYPE_DANGER  = "danger";

    /** @var array user friendly named type */
    protected static $typeName = [
        self::TYPE_INFO    => 'Information',
        self::TYPE_WARNING => 'Attention',
        self::TYPE_SUCCESS => 'Succès',
        self::TYPE_DANGER  => 'Danger',
    ];

    /**
     * @param  string $typeShortName
     * @return string
     */
    public static function getTypeName($typeShortName)
    {
        if (!isset(static::$typeName[$typeShortName])) {
            return "Unknown type ($typeShortName)";
        }

        return static::$typeName[$typeShortName];
    }

    /**
     * @return array<string>
     */
    public static function getAvailableTypes()
    {
        return [
            self::TYPE_INFO,
            self::TYPE_WARNING,
            self::TYPE_SUCCESS,
            self::TYPE_DANGER
        ];
    }

Here is an example of use:

<?php
echo MessageTypeEnum::TYPE_INFO;
//info
echo MessageTypeEnum::getTypeName(MessageTypeEnum::TYPE_INFO);
//Information

Now, you need to adapt your Entity:

<?php

class Message
{
    /**
     * @var string
     * @ORM\Column(name="type", type="string", length=255, nullable=false)
     */
    private $type;

    //...

    /**
     * @param string $type
     * @return Message
     */
     public function setType($type)
     {
         if (!in_array($type, MessageTypeEnum::getAvailableTypes())) {
             throw new \InvalidArgumentException("Invalid type");
         }

         $this->type = $type;

         return $this;
     }
}

And this is the form: (MessageType.php)

<?php

public function buildForm(FormBuilderInterface $builder, array $options)
{
    $builder
        ->add('content')
        ->add('type', 'choice', array(
            'required' => true,
            'choices' => MessageTypeEnum::getAvailableTypes(),
            'choices_as_values' => true,
            'choice_label' => function($choice) {
                return MessageTypeEnum::getTypeName($choice);
            },
        ))
    ;
}

And tadaaa it works!

Your Form should look like this:


A la découverte d'Hubot

Je regardais l'autre jour cette conférence d'Alain Hélaïli à propos sur le fonctionnement interne de [Github.com](https://github.com). Au...… Continue reading

Développeur expatrié à Dublin

Published on April 23, 2017

Chaining Javascript filters recursively

Published on March 28, 2017