Symfony Entities and Traits
I’m currently working on a Symfony-based project whose data model is far from being stable and all its properties known; for this reason, three Doctrine entities have a common private property called “attributes”, declared as json_array: by mapping and converting array data based on PHP’s JSON encoding functions, I’m sure that any other additional entity properties can be added to the array, without altering database structure or application logic.
The following piece of code shows one of the entity.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
|
Of course this feature comes with a little of logic to be implemented, so that controllers and repositories can use them:
1 2 3 4 5 6 7 8 9 |
|
Instead of duplicating all these methods in each entity class, I found that PHP’s traits offers a good and nice tradeoff.
Traits
As of PHP 5.4.0, PHP implements a method of code reuse called Traits. Traits are a mechanism for code reuse in single inheritance languages such as PHP. A Trait is intended to reduce some limitations of single inheritance by enabling a developer to reuse sets of methods freely in several independent classes living in different class hierarchies. The semantics of the combination of Traits and classes is defined in a way which reduces complexity, and avoids the typical problems associated with multiple inheritance and Mixins.
I created a trait called “AttributeTrait” in the same namespace of my entities and implemented in it the methods listed before.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
|
The nice aspect is that, the traits and the class that uses it, are merged togheter, as they were a whole class: this means that Doctrine will
create a table with all the properties declared in the entity class and those belonging to the traits.
The $this
reference points to the container class, the entity instance in this case, so no changes to the code should be made.
Accessing the property from Twig
To complete the picture and make it more flexible even inside a Twig templates, I also implemented the special method __call
,
to make the code more readable.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 |
|
From within a Twig template, I could use the typical syntax instance.property
.
For example:
1 2 3 4 5 |
|
From within a Twig template:
1
|
|
The width
property doesn’t exist in class Archetype
, but was added as dynamic property with trait support; Twig will call the
corresponding method getWidth
which is intercepted from special method __call
and converted in an attribute access.