Traits in PHP: Proper way of implementation
Trait is very useful concept in OOP PHP. Although it is very similar to php class but it has so many different uses in OOP approach. In this article i will try to describe how to use trait in a proper way & when we use trait instead of class and common trait scopes.
The main benefit of traits is its re-usable nature. The PHP language is a single inheritance language. This means that any given class can only extend a single other class. As an example, let’s say you have two base classes:
Unfortunately, as it stands in PHP, you cannot perform multiple inheritance by extending classes. You can extend either BaseA or BaseB, but not both at the same time:
But what if you want the functionality of both of these in a single class? Traits can solve this problem:
This method of inheritance is known as “Horizontal Reuse”. It is intended to reduce code duplication and share code horizontally.
Using Traits
As described above, traits are very easy to use. In their most basic form, you declare a trait using the trait
keyword:
You can then have classes which use this trait:
Traits can also contain class properties:
Basically, when a trait is used in a class, it is more or less directly copied into the class. I’ll go over some basic properties of traits, and some common use cases.
Trait Scope
One thing to note is that the scope of functions and properties within a trait are inherited by the child class. This means a private
, protected
, or public
object will act in the class the same way it acts as it does in the trait. One way to think about it is that the contents of the trait are more or less directly copied into the classes which use them. What does this mean for each scope specifically?
Private
Unlike single inheritance, private scope in a trait will be available to the extending classes. Take this example:
In the above code, the ExtendingClass
will throw an error - this is because it is trying to access a function which is private to PrivateClass
.
Protected
Protected scope for a trait means that any class which extends the trait, or the children of the trait are able to access the function or variable. In the previous example, if privateFunc
were a protected
function, then ExtendingClass
would be valid.
Public
Anyone can access the variable or function. Simple as that.
Naming Conflicts
Sometimes, it is possible that you need to import a trait into a class, but there is a conflicting function or variable name. This can be solved using either the as
or insteadof
operator:
The insteadof
specifies that you want to use someFunc
from A instead of B. The as
operator specifies a different name for the imported function - basically an alias. If you use the insteadof
operator and don't alias the replaced function, then it is essentially discarded. In the case above, B::someFunc
was discarded since it was not aliased.
In above i try to describe using of trait in a proper manner.