Traits are available in PHP since version 5.3. But yet so many people say when I ask about traits on the job interview: “Yes, I have heard/read about it but never used in real projects”.
Traits is a powerful tool when you know how to use it. The mission of this article is to introduce them by defining a problem they can solve and to solve it.
Call Girls In Mukherjee Nagar 📱 9999965857 🤩 Delhi 🫦 HOT AND SEXY VVIP 🍎 SE...
Using traits in PHP
1. Using traits in PHP
1. Introduction
Traits are available in PHP since version 5.3. But yet so many people say when I ask about
traits on the job interview: “Yes, I have heard/read about it but never used in real projects.”.
Traits is a powerful tool when you know how to use it. The mission of this article is to introduce
them by defining a problem they can solve and to solve it.
2. The Problem
Let’s assume we are designing the 2D game called “Toy War”. Our current task is to implement
all fighting units, which are for now: Tanks, Jet Fighters, Spy Airplanes and Air Defence Towers.
Of cause we want to create a class for each unit. To have a good architecture we also need to
define some abstractions that will help us to structurize our code.
Let’s see what features all the units have. Some of them:
● have their position on the map
● can move
● can turn left and right
● can fly
● have a gun (can fire).
Each feature provides some functionality which turns out basically as methods in our code. For
example, ‘having positions’ means we can call getPosition() method and get a 2d vector,
and ‘having gun’ stands for getGunDirection(), turnGun($degrees) and fire().
Let’s build a simple ‘Feature / Unit’ map to see what features each of the units do have:
Feature / Unit Tank Jet Fighter Spy Airplane Air Defence Tower
Has position + + + +
Can move
forward
+ + + -
Can turn + + + -
Can fly - + + -
Has a gun + + - +
If you will look for a common features for all units you’ll see that the only one is ‘Having
position’. It means that the only abstraction we can define is a Unit which just has
getPosition() method.
Going further we could define a MovableUnit which will provide ‘moving forward’ and ‘tuning’
features as they are applicable to the same units.
2. At this point we have a pretty straightforward inheritance structure:
But we still have two features to implement: ‘flying’ and ‘having gun’. If we forget for a moment
the moving and arming functionality and draw a diagram for a flying feature we get:
3. Leaving flying and and moving behind the scene and working with arming we get:
4. But if we try to merge all these diagrams and build the inheritance structure for all features than
we get:
5. This diagram says we need to inherit multiple classes for most of our units. And that is
impossible in PHP.
3. The Solution
Here is what the Traits come for. The mission of a Trait is to provide some atomic functionality
for an object. A Trait defines a single feature (i.e. movable or flyable) and could be applied to
any class. The key feature of Traits is that you can apply any number of them to your class. It let
you compose a class from different features it has and as a result -- to build more complicated
but elegant architecture which will be much more adequate to the real world.
With using of Traits our diagram turns to:
6. The SpyPlane, JetFighter, Tank and Tower are inherited from Unit and are using only the
features they have. Which is great because it meets all the requirements and is fully
implementable in PHP.
Let’s see the code.
4. The Code
<?php
/**
* Abstract Unit class.
* Implement 'has position' feature.
*/
abstract class Unit
{
protected $position;
public function getPosition()
{
return $this->position;
7. }
}
/**
* Implement 'moving' feature.
*/
trait Movable
{
public function move() { /* ... */ }
public function turn($degrees) { /* ... */ }
}
/**
* Implement 'having gun' feature
*/
trait Armed
{
protected $gunDirection;
public function getGunDirection() {
return $this->gunDirection;
}
public function turnGun($degrees) { /* ... */ }
public function fire() { /* ... */ }
}
/**
* Implement 'flying' feature
*/
trait Flyable
{
public function blastOff() { /* ... */ }
public function fly() { /* ... */ }
public function land() { /* ... */ }
}
/**
* Implement the Tank which has position, can move and definitely has a gun
*/
class Tank extends Unit
{
use Movable, Armed;
}
8. /**
* Implement the Jet Fighter which has position, can move, fly and has a gun
*/
class JetFighter extends Unit
{
use Movable, Flyable, Armed;
}
/**
* Implement the Spy Plane which has position, can move and fly but is
unarmed.
*/
class SpyPlane extends Unit
{
use Movable, Flyable;
}
/**
* Implement the Air Defence Tower which has position and gun but can't move
or fly.
*/
class Tower extends Unit
{
use Armed;
}
As you can see using traits is as easy as extending the abstract class. And like the methods of
the ancestors the traits method could be overwritten by the descendant. But the syntax differs.
For example:
/**
* Implement the Tank which has position, can move and definitely has
a gun
*/
class Tank extends Unit
{
use Movable;
use Armed {
fire as traitFire;
};
9. public function fire()
{
/**
* Do tank specific fire actions
*/
$this->traitFire();
}
}
Here we have used as operator to give an alias for fire() method so we can implement our
specific fire() using the method from the Trait.
PHP also provides the conflict resolving mechanism, ability to change visibility of methods and
other useful functionality which you can learn at http://php.net/traits. Note that traits are
available since PHP 5.4 which is very widespread already. So i bet you can start using it right
now.
5. Wrap up
Traits let us think of architectural model as of the definition of features represented as Traits and
Classes which are composed from Traits in such many ways as do objects in real life. But the
well-known hierarchical model is not being completely substituted with the compositional one.
They complement each other giving us the ability to design graceful architectures for apps we
build.
About Author
Max Gopey is a PHP Team Leader in Ciklum who currently works on Magento projects.
He has 6 year experience in developing PHP applications for the web including e-commerce
and document management systems.