In PHP you may realise that you can only extend one class, single inheritance. And you will start to see frustrations in being only to extend one at a time. Sometimes you can't just keep extending classes. Sometimes you end up in a framework extending length of oh say 15 classes or perhaps even more. Sometimes it is not necessary to go this far to ensure classes inherit functionality. Have you ever wanted to share methods functionality that is generally across a broad set of classes and not have to inherit from a parent?

What is a trait?

PHP 5.4 introdued a new language feature called Traits. A trait is like a mixin, it allows you to call upon other functionality into your class. Traits solve the problem of allowing you to import common functionality into classes whenever you like and at whatever level in the inheritance chain. A single class or a class that has inherited 15 classes, you can then just import your trait and it's functionality. A trait cannot be instantiated or used on its own. It's purpose is to give shared functionality to classes. A trait allows you to add functionality to the methods, where as an interface outlines a blueprint of methods. So shall we see a trait? [php] trait CommonStuff { public function getIdea(){ return 'the awesome idea'; } } [/php] So this is a trait. Simple stuff and looks like a class bar the keyword is trait instead of class. How do we use it with another class? [php] class Model { use CommonStuff; } class SuperModel { use CommonStuff; } [/php] We use the use keyword to import traits at the top of our class. This means the traits functionality is then free to use throughout our class and any child classes that inherit from this class. You can then access the traits methods on each class like so: [php] $model = new Model; $model->getIdea(); // the awesome idea $supermodel = new SuperModel; $supermodel->getIdea(); // the awesome idea [/php] Well lets see a trait against regular class inheritance.

Examples

So lets use an example, we have a set of model classes and all of them could share a method to update the time on each model in the database. We'll also have a getLatest method that should get the latest object of the model from the DB. Now normally their would be a base model class and that would have the methods in and all the other classes that extend would inherit this method: [php] class Model { public function updateTime() { // update time } public function getLatest() { // get latest } } class User extends Model {} class Post extends Model {} $user = new User(); $post = new Post(); $user->updateTime(); // get time $post->updateTime(); // get time [/php] So they all inherit this functionality and works nicely as expected. Now Another class that wishes to be exposed to this functionality but not all the methods in the parent Model class. All it wants is the getLatest method. We shall call this new class Simple. This new class does not have a timestamp on it and has no need for that method. It only wants the getLatest method. It would be ideal to just move the getLatest method into its own section of code that could be imported into classes as and when we need them. Step forward traits. [php] trait CommonStuff { public function getLatest() { // get latest } } class Model { use CommonStuff; public function updateTime() { // update time } } class User extends Model {} class Post extends Model {} class Simple { use CommonStuff; } $user = new User(); $post = new Post(); $simple = new Simple(); $user->getLatest(); // get latest $post->getLatest(); // get latest $simple->getLatest(); // get latest [/php] So a trait is the in between. It can be brought into a class at any level or given point. Its the freedom to import it's scope into your chosen class. Think of it like the following diagrams:

base-extends-relationship


This shows the current relationship we have setup. If we pull in a trait for our seperate class and of course now original classes it will work like so:

trait-relationship


This is only pulling in one trait, you have the ability to pull in multiple traits to your class if you wish: [php] class Simple { use CommonStuff, MoreCommonStuff; } [/php]

Any Negatives to using Traits?

Well yes like anything, their are drawbacks. It could be very easy for your code to become very bloated in a trait while you try to share functionality broadly across classes. Debugging classes becomes a bit of a longer process as you then need to go searching for the trait and then the functionality it has.

Conclusion

I really like Traits and think they are one of the great features that has come into PHP in the 5 series of releases. They are used quite nicely within Laravel so they definitely have a place for use within your code. I also think they can be used nicely in wordpress, which I will visit in a future post. Thanks for reading.

Monthly Archives: August 2015

Traits

In PHP you may realise that you can only extend one class, single inheritance. And you will start to see frustrations in being only to extend one at a time. Sometimes you can’t just keep extending classes. Sometimes you end up in a framework extending length of oh say 15 classes or perhaps even more.

Read more