The purpose of this post is actually somewhat inquisitive rather than informative, I will go over the basics of traits and provide and example. However it would be great if anybody from the community could point me in the direction of a well implemented trait, other than Fooman’s which I mention below.
What is a trait
A trait helps use with code reuse. You should think of it like copy and paste. If two implementations share the same functionality they may share methods. In this case you should almost never write those methods twice, you should either refactor your dependencies, think about inheritance or use a trait
A trait can own multiple methods and then you can use those traits in your classes.
When to use a trait
Some months ago myself, Vinai Kopp, Phil Winkle and Fooman were discussing when/if to use traits within your PHP code. You can see the Twitter discussion here.
Both sides to the discussion had interesting points, at the time I agreed with Vinai and couldn’t really see the advantage of using a trait. I am still pretty undecided on the matter, I’m not sure whether this whole discussion just comes down to personal preference or I am missing something.
I have made an example of a trait in use below for people who haven’t seen them before. Fooman also provided an example with in Magento 2 which he wrote for the platform, this is a lot better use case than mine.
Okay, so lets say we have to write two objects. The first one is a ticket office for a bus station, lets call is BusStationTicketOffice() and the second is a ticket office for an airport, lets call this one AirportTicketOffice().
So both ticket offices need the ability to be able to create a passenger and set them into some kind of passenger repository, so first let’s create a PassengerHandlerInterface.
The problem is, the BusStationTicketOffice office and AirportTicketOffice are going to need the same logic when it comes to setting passengers into a repository or a protected variable. However they have already been tightly coupled to other implementations.
# How do we get around this?
I would almost always use dependency injection. IE rather than having my BusStationTicketOffice implement PassengerHandlerInterface I would inject some sort of PassengerRepository which implements the methods needed.
However in this example I am going to use a trait. As it is the BusStationTicketOffice and AirportTicketOffice job of creating customers from the data presented to them, we could do something like this:
This is actually a pretty bad example of a use case for a trait, I would almost certainly us DI here.
I suggest taking a look at Fooman’s example, it is the best I have seen of a trait.
I would really like to see some more real life examples of traits, Kalen Jordan suggested using a trait for a logger which I could see as being useful.