Default behavior when creating a EnumType form element is that the choice labels displayed to the user are the enum names. This PR adds an example of how to use a function inside an enum to return labels and how to bind this function to the form element.
- Loading branch information
There are no files selected for viewing
Original file line number | Diff line number | Diff line change | ||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
@@ -56,6 +56,40 @@ This will display a ``<select>`` tag with the three possible values defined in | |||||||||||||
the ``TextAlign`` enum. Use the `expanded`_ and `multiple`_ options to display | ||||||||||||||
these values as ``<input type="checkbox">`` or ``<input type="radio">``. | ||||||||||||||
|
||||||||||||||
Since the label displayed in the ``<select>`` options is the enum name, you might sometimes | ||||||||||||||
want more flexibility as PHP strongly restricts the usable characters for those. | ||||||||||||||
You could do this by implementing a function in your enum class which returns a label | ||||||||||||||
or even a translation string for each possible enum:: | ||||||||||||||
|
||||||||||||||
// src/Config/TextAlign.php | ||||||||||||||
namespace App\Config; | ||||||||||||||
|
||||||||||||||
enum TextAlign: string | ||||||||||||||
{ | ||||||||||||||
case Left = 'Left/Start aligned'; | ||||||||||||||
case Center = 'Center/Middle aligned'; | ||||||||||||||
case Right = 'Right/End aligned'; | ||||||||||||||
|
||||||||||||||
public function label(): string | ||||||||||||||
{ | ||||||||||||||
return match ($this) { | ||||||||||||||
self::Left => 'text_align.left.label', | ||||||||||||||
self::Center => 'text_align.center.label', | ||||||||||||||
self::Right => 'text_align.right.label', | ||||||||||||||
}; | ||||||||||||||
} | ||||||||||||||
} | ||||||||||||||
|
||||||||||||||
You can then use the ``choice_label`` option of ``EnumType`` with a function that | ||||||||||||||
returns the label:: | ||||||||||||||
|
||||||||||||||
->add('textAlign', EnumType::class, [ | ||||||||||||||
'class' => TextAlign::class, | ||||||||||||||
'choice_label' => static function (TextAlign $choice): string { | ||||||||||||||
return $choice->label(); | ||||||||||||||
There was a problem hiding this comment.
Suggested change
There was a problem hiding this comment. This would work if you only needed to display the labels in your form, but if you also need them to appear anywhere else in your application I think adding a method in the enum class is a better solution. I don't think adding presentation methods in enum classes is a bad practice. There was a problem hiding this comment. If I had different places where I needed the label, I would go with a separate class that maps enum instances to labels to be honest. There was a problem hiding this comment. That might be a way to do it but maybe a bit overkill. Even the PHP documentation suggests adding a label method in enum classes in their examples : https://www.php.net/manual/fr/language.enumerations.examples.php There was a problem hiding this comment. I don't know what to say here. I think both of you gave good reasons to do opposite things. Let's ask @wouterj and @OskarStark. Thanks! There was a problem hiding this comment. I agree with @xabbuh here. I understand your point, @robinbrisa, and it is also proven by the official PHP docs. However, I would say that an enum can ship a generic presentation layer. The labels provided in this example indirectly couple the Enum's presentation layer to the Symfony Translation component - without it, the labels render worse human readable than their default string representation from the There was a problem hiding this comment. Another way to see it would be to have |
||||||||||||||
}, | ||||||||||||||
]) | ||||||||||||||
|
||||||||||||||
|
||||||||||||||
Field Options | ||||||||||||||
------------- | ||||||||||||||
|
||||||||||||||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Adding this method to the enum class starts mixing data and presentation which I would not advise. Let's configure the choice label using a closure instead (see comment below).