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.

A Trait is similar to a class, but only intended to group functionality in a
fine-grained and consistent way. It is not possible to instantiate a Trait on
its own. It is an addition to traditional inheritance and enables horizontal
composition of behavior; that is, the application of class members without
requiring inheritance.

Precedence

An inherited member from a base class is overridden by a member inserted
by a Trait. The precedence order is that members from the current class
override Trait methods, which in turn override inherited methods.

Example #2 Precedence Order Example

An inherited method from a base class is overridden by the
method inserted into MyHelloWorld from the SayWorld Trait. The behavior is
the same for methods defined in the MyHelloWorld class. The precedence order
is that methods from the current class override Trait methods, which in
turn override methods from the base class.

Conflict Resolution

If two Traits insert a method with the same name, a fatal error is produced,
if the conflict is not explicitly resolved.

To resolve naming conflicts between Traits used in the same class,
the insteadof operator needs to be used to choose exactly
one of the conflicting methods.

Since this only allows one to exclude methods, the as
operator can be used to add an alias to one of the methods. Note the
as operator does not rename the method and it does not
affect any other method either.

Example #5 Conflict Resolution

In this example, Talker uses the traits A and B.
Since A and B have conflicting methods, it defines to use
the variant of smallTalk from trait B, and the variant of bigTalk from
trait A.

The Aliased_Talker makes use of the as operator
to be able to use B's bigTalk implementation under an additional alias
talk.

If a trait defines a property then a class can not define a property with
the same name unless it is compatible (same visibility and initial value),
otherwise a fatal error is issued.
Before PHP 7.0.0, defining a property in the class with the same visibility
and initial value as in the trait, raised an E_STRICT notice.

Note that the "use" operator for traits (inside a class) and the "use" operator for namespaces (outside the class) resolve names differently. "use" for namespaces always sees its arguments as absolute (starting at the global namespace):

As already noted, static properties and methods in trait could be accessed directly using trait. Since trait is language assisted c/p, you should be aware that static property from trait will be initialized to the value trait property had in the time of class declaration.

I think the best conceptual model of an incorporated trait is an advanced insertion of text, or as someone put it "language assisted copy and paste." If Foo1 and Foo2 were defined with $_bar, you would not expect them to share the instance. Similarly, you would expect Foo3 to share with Foo2, and it does.

Viewing this way explains away a lot of the 'quirks' that are observed above with final, or subsequently declared private vars,

If I want to extend more I need to make a cascade of classes:<?phpclass NiceBrain extends Brain { use BrainLog;}class CrazyBrain extends NiceBrain { use BrainMad;}$brain = new CrazyBrain;$brain->ask('What we gonna do tonight?');// Will output 'I don't wanna talk with you.' or normal response// but logging only in case BrainMad has a good mood?>

Because using of multiple traits will call only one selected in section "use Trait;".

(It's already been said, but for the sake of searching on the word "relative"...)

The "use" keyword to import a trait into a class will resolve relative to the current namespace and therefore should include a leading slash to represent a full path, whereas "use" at the namespace level is always absolute.

The difference between Traits and multiple inheritance is in the inheritance part. A trait is not inherited from, but rather included or mixed-in, thus becoming part of "this class". Traits also provide a more controlled means of resolving conflicts that inevitably arise when using multiple inheritance in the few languages that support them (C++). Most modern languages are going the approach of a "traits" or "mixin" style system as opposed to multiple-inheritance, largely due to the ability to control ambiguities if a method is declared in multiple "mixed-in" classes.

Also, one can not "inherit" static member functions in multiple-inheritance.

Using AS on a __construct method (and maybe other magic methods) is really, really bad. The problem is that is doesn't throw any errors, at least in 5.4.0. It just sporadically resets the connection. And when I say "sporadically," I mean that arbitrary changes in the preceding code can cause the browser connection to reset or not reset *consistently*, so that subsequent page refreshes will continue to hang, crash, or display perfectly in the same fashion as the first load of the page after a change in the preceding code, but the slightest change in the code can change this state. (I believe it is related to precise memory usage.)

I've spent a good part of the day chasing down this one, and weeping every time commenting or even moving a completely arbitrary section of code would cause the connection to reset. It was just by luck that I decided to comment the

"__construct as primitiveObjectConstruct"

line and then the crashes went away entirely.

My parent trait constructor was very simple, so my fix this time was to copy the functionality into the child __construct. I'm not sure how I'll approach a more complicated parent trait constructor.

Traits are useful for strategies, when you want the same data to be handled (filtered, sorted, etc) differently.

For example, you have a list of products that you want to filter out based on some criteria (brands, specs, whatever), or sorted by different means (price, label, whatever). You can create a sorting trait that contains different functions for different sorting types (numeric, string, date, etc). You can then use this trait not only in your product class (as given in the example), but also in other classes that need similar strategies (to apply a numeric sort to some data, etc).

Traits broke OOP.Exapmle: Let we have an object with one method. Creator of the class used traits to overload that method.We write client code. So there is no way to know what this object do with that method because the same class with different traits in it will do different things.

It's evident that traits are evil in your code try to use OOP instead of them