unixo's blog

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.

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.

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.

From within a Twig template, I could use the typical syntax instance.property.

For example:

12345

<?php$archetype=newArchetype();$archetype->setAttribute('width',25.4);echo$archetype->getWidth();// this will invoke __call

From within a Twig template:

1

<p>Width: {{ archetype.width }}</p>

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.