Traits and Grafts, PHP6 Gold

Although PHP5.3 is still hot off the press, and a very exciting release in its own right. I must say I’m far more excited about the grafts and traits that have been proposed for PHP6. While PHP6 is still a fair ways off from being released, Stefan Marr has backported the changes to PHP5.3 so the adventurous can try them now.

Traits and Grafts?

Traits and grafts as proposed, offer an alternative to creating code reuse. Normally inheritance creates code reuse by allowing you to sub class and extend features. This can create deep trees of classes, and often times you can end up with classes containing features they didn’t really need. Traits solve this by allowing horizontal code reuse. Instead of building vertical chains of classes, you use traits to create feature blocks. You then combine these blocks voltron style to create objects. Grafts are similar to traits, but different in that they allow you to ‘graft’ methods from one class onto another. So instead of discrete feature blocks that are combined together, you can pick and choose the methods you want to create classes.

Enter the mixin

One of the great features of Ruby and Javascript is the ability to create mixins. Ruby does this through open classes and Javascript by virtue of having prototypal inheritance. However, creating mixin type functionality in PHP is a bit of a headache that requires using the magic __call and delegation to inner objects. While functional, this setup lacks some elegance, and requires additional code. Grafts and traits resolve the need for additional code and make implementation of method delegation much more elegant. Consider the following:

Show Plain Text
  1.  
  2. trait Sluggable {
  3.     function slug() {
  4.         return preg_replace('/[^\D\d]*/'), '_', strtolower($this->title));
  5.     }
  6. }
  7.  
  8. class Post extends Model {
  9.     use Sluggable;
  10. }
  11.  

Post will now have a slug() method, that is no different than any other class methods. While the above is an overly simple example, I think it shows some of the power that traits can offer. You will no long need deep hierarchies of classes in order to enable code reuse. Instead you can write blocks of functionality and as long as you design things in a generic way, reuse them as needed. If you are working from a CakePHP perspective, traits/grafts could easily replace Behaviors and the behavior method delegation system. Doing so would remove overhead and simplify the in your code. In closing, I’m very excited about PHP6, and what it offers. Thanks to everyone who works on the PHP project and makes it so much more than the template language that could.

Comments

This is great. Looks just like Modules in Ruby!

In you example, what is $this refering to inside of the trait?

Will this automatically inherit $this from the class that is using it?

Éber Freitas Dias on 12/10/09

Hmmm, will this herald the embarkation of development of a new, PHP6 only, Cake4 branch, what do you reckon Mark?

Neil Crookes on 13/10/09

Neil: Probably not. Considering there are not even a PHP6 downloadable binaries, it would be jumping the gun a bit. Kind of like all those PHP6 books that have already been published.

mark story on 14/10/09

Now I am just hoping for named parameters or array shortcuts a() instead of array(). Those 3 things might reduce codesize on some fancy frameworks ;) a lot ;)

ionas82 on 20/10/09

Éber: $this will be the class implementing the trait.

ionas82: I remember seeing suggestions that PHP use [1, 2, 3] as an alternate syntax for arrays, but I don’t think it gained any traction.

mark story on 20/10/09

no it did not. I think the core team voted 70% against it and the community team 30% against it.
…and I am sad about it. any shorter way of adding arrays would be just great. a() for instance instead of array() (and that would NOT be too hard to maintain)

anyway its the way it is. I am off to bed and building cake apps on your(and a very little our) framework love ;)

ionas82 on 21/10/09

I guess the question is, like multiple inheritance, which Sluggable do you choose if along your inheritance chain you get more than one implementation to use?

wakes on 22/3/10

Have your say:

*
* You can use Textile markup, but be reasonable