Cover for Dealing with Enum in a Symfony App with Doctrine2 as ORM

Dealing with Enum in a Symfony App with Doctrine2 as ORM

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 a message object which contains 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 provides 2 solutions for MySQL Database. What happens 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 kid on a ship

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:



About the author

Maxence Poutord

Hey, I'm Maxence Poutord, a passionate software engineer. In my day-to-day job, I'm working as a senior front-end engineer at Orderfox. When I'm not working, you can find me travelling the world or cooking.

Follow @_maxpou

Recommended posts