Traits and Horizonal Design

One of the newest and most powerful features in PHP 5.4 is Traits, or the ability to implement horizontal design into your application. In these slides we will take a look at what traits are and how
…

One of the newest and most powerful features in PHP 5.4 is Traits, or the ability to implement horizontal design into your application. In these slides we will take a look at what traits are and how to use them (including examples of when to use horizontal design) as well as review the ReflectionClass and how it can be used to describe the traits in your code base.

4.
WHAT ARE 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.”

5.
WHAT ARE TRAITS
“[They are] similar to a class, but intended to
group functionality in a fine-grained and
consistent way. It is not possible to
instantiate a Trait on it’s own. It is an
addition to traditional inheritance and enables
horizontal composition of behavior.”

6.
HUH?
To think of traits in another way, think of
traits as characteristics. People have unique
traits that makeup who they are- hair color,
eye color, height, weight, likes, dislikes, etc.
But it is the combination of these traits
working together that make them who they
are.

7.
HUH?
In the same way Traits in PHP are collections
of methods that can be imported into classes.
Each stands alone by itself (ie brown hair),
but becomes part of something more when
inherited into the class (he has brown hair
and brown eyes).

8.
HUH?
Traits are designed to allow for code
reusability and extendibility. These groups of
methods are designed to be pulled in and
used by any other class. Like Midas’ touch,
they seamlessly become part of the class
utilizing them.

12.
THE IDEA BEHIND HORIZONTAL DESIGN
Traditional vertical design is very limiting. To help
address these limitations there has been an increased
focus on Dependency Injection, or injecting classes into
another class to allow the class to access additional
methods and properties. However, even this approach
is very limited in its capabilities. It’s important to note
that Horizontal Design does not replace Dependency
Injection, but rather ensures correct usage of it.

19.
BUILDING THE APP
In the next few slides we will take a look at
the difference between building a simple app
vertically, verses horizontally.
The app will utilize the same 5 files in both
cases.

20.
BUILDING A HORIZONTAL APP
<?php
Pull in the Traits, just like you would namespaces only within the class
/**
* @package ressf
* @category ressf
*/
class ressf {
use ressfbasevalidators;
use ressfbaseextenders;
use ressfpluginsvalidators;
use ressfpluginsextenders;!
Full source on GitHub: http://github.com/mikestowe/ressf Branch: master

23.
BUILDING A VERTICAL APP
<?php
In the __construct() method setup properties to store the Extenders
and Validators objects. Since these objects will manipulate and make
use of properties and methods within the instantiated ressf object we
need to pass the ressf object to them as well.
Now we can do the basic operations, utilizing the properties we just
setup.
/**
* Construct
* @return ressf
*/
public function __construct()
{
$this->extendersClass = new extenders($this);
$this->validatorsClass = new validators($this);
$this->tags = array_merge($this->validatorsClass->baseTags, $this->validatorsClass->tags);
$this->extenders = array_merge($this->extendersClass->baseExtenders,
$this->extendersClass->extenders);
}!
Full source on GitHub: http://github.com/mikestowe/ressf Branch: php53

31.
THE DIFFERENCE
By using horizontal design we were not only able to make
the application more efficient, we were also able to reduce
the amount of code by 34%! That’s just for a small, fairly
simple application containing just 5 files and 454 lines of
code!
195 Additions | 39 Deletions
https://github.com/mikestowe/ressf/compare/php53

32.
THE BENEFITS
• Reduces the amount of code needed
• Reduces Dependency Injection requirements
• Provides seamless integrations into classes
• Code can be reused by multiple classes
• Allows for properties of dependencies to be included

33.
THE BENEFITS
• Allows for multiple interactions and eliminates vertical
asphyxiation/ dead ends
• Plug and play friendly (traits play with other traits as long
as there are no conflicts)
• No class name conflicts (as with namespaces)

34.
THE CHALLENGES
• Property Conflicts – properties in traits and calling classes
must be exactly the same otherwise an error is thrown
• Method Conflicts/ Overrides – traits containing the same
methods may result in the wrong method being called
• Harder to navigate code (ie locating methods/ properties)
• Limited to PHP 5.4+

35.
THE DIFFERENCE BETWEEN CLASSES,
ABSTRACTS, INTERFACES
Traits are similar to abstract classes in that they cannot be
instantiated by themselves. However, unlike an abstract
class traits are not extendable. You can use traits within
other traits however, just as you would in a class through the
use keyword.
Traits can contain methods and properties, something that
makes them unique in PHP.

36.
TRAIT HIERARCHY AND CLASS
OVERRIDES
Because traits are applied at a horizontal level there is no
hierarchy applied to the methods. Rather, if two traits on the
same vertical plane contain identically named methods a
fatal error will be thrown explaining which method could not
be applied to the class.
If a class has an identically named method it will override
the trait method.

38.
CLASS OVERRIDES
<?php
However, if a trait is included in a child class, and shares the
same method name with a method in the parent class, the trait
will override the parent method, just as if the child class had the
same method as the parent class.
In this case parent methods will need to be referred to using the
parent::method()
syntax.
trait traitTwo
{
public function a()
{
return parent::a();
}
}!

39.
TRAIT ALIASING
To use traits containing identically named methods or to make
a trait method available within a class we can alias the trait
using the as and insteadof keywords.
The as keyword will give the method an alias to reference it
by
The insteadof keyword tells the compiler to use that traits
method instead of a different identically named method from
another trait.

41.
TRAIT ALIASING
<?php
When using multiple use declarations within your class it is
important to place the insteadof delcaration before the as
declarations to avoid conflicts.
<?php
/* … */
class myClass
{
use traitOne, traitTwo
{
traitTwo::test insteadof traitOne;
traitOne::test as one;
}
}
!

44.
TRAIT METHOD DEPENDENCIES
<?php
Often times a trait method may require interaction with a
class method. To ensure the class method is defined you can
create an abstract method in the trait, which if called will
throw a fatal error:
<?php
trait myTrait
{
public function test()
{
$this->doSomething();
}
public abstract function doSomething();
}
class myClass
{
use myTrait;
}
(new myClass())->test();!

45.
TRAIT PROPERTIES
One of the advantages of traits in PHP over other languages is
that PHP allows traits to contain properties. This allows you
to pull in a full set of code and it’s dependencies without
having to manually add properties to your calling class.
However, it is important to be careful when using properties
as any properties declared in both the trait and the calling
class must be identical in visibility, type, and value.
The exception to this is when using a data-type of string for
one, and a data-type int for another, as long as the state and
value are identical.

49.
TRAIT FUNCTIONS
trait_exists()
– similar to class_exists(), this function
checks to see if the trait has been defined and returns an
boolean.
get_declared_traits()
– similar to
get_declared_classes(), this function returns an array of
traits that have been declared.

50.
REFLECTION CLASS
getTraits()
returns an array of all traits used in a class,
while getTraitNames()
returns an array of the trait names
in a class.
getTraitAliases()
returns an array of aliases linked to its
original trait and method.
isTrait()
returns whether or not a tested object is a trait
http://php.net/manual/en/class.reflectionclass.php

52.
MORE USE CASES
BASE CONTROLLER
MOD. CONTROLLER
API CONTROLLER
ACTUAL
What happens if we need to
modify the modified controller?
What if the API Controller needs
new dependencies because our
application was updated?

53.
MORE USE CASES
BASE CONTROLLER
MOD. CONTROLLER
ACTUAL
Traits allow us to pull in classes, properties,
and methods without having to create a
dependency chain, leaving the modified
controller easily accessible and updatable.
API CONTROLLER

54.
MORE USE CASES
BASE CONTROLLER
MOD. CONTROLLER
MODIFIERS
ACTUAL
API CONTROLLER
Traits also allow us to modify existing classes without
overriding them in the vertical hierarchy. And keeps
source code isolated and reusable.