DEV Community

Eelco Verbrugge
Eelco Verbrugge

Posted on

PHP Traits Explained

In line of my previous blogs PHP Interfaces Explained and PHP Abstract Classes Explained, I'll explain PHP Traits today.

In PHP a child class can inherit only from one single parent. This allows a class to reuse methods from vertically hierarchy by extending an Abstract class.

If you like to reuse methods in many different classes in horizontally hierarchy, we use Traits. Traits are used to group methods and implement in multiple classes. Traits can't be initiated on it's own like a normal class could.

For example

Let's say we would like to check if a user has access in many classes:

trait Access
{
    public function hasAccess(string $username): bool
    {
        //..Check if $username has access
    }
}
Enter fullscreen mode Exit fullscreen mode

Everyone who can access Files, is allowed to download them. To use this Trait into our class:

class File
{
    use Access;

    public function download(string $username): Response
    {
        if ($this->hasAccess($username)) {
            //..Download file x
        }
    }
}
Enter fullscreen mode Exit fullscreen mode

Wherever you implement your Trait with use Access; you are able to refer to $this->yourMethod() as of it would be one of this class. Which in this case is only hasAccess().

Multiple inheritance

What if you need multiple inheritance to reuse various methods in many different classes in horizontally hierarchy?

This is easily done, let's create an other one:

trait Ability
{
    public function canUpload(string $username): bool
    {
        //..Check if $username can upload
    }
}
Enter fullscreen mode Exit fullscreen mode

We want to check if our $username can access files and is allowed to upload as well:

class File
{
    use Access, Ability;

    public function upload(string $username): Response
    {
        if ($this->hasAccess($username) && $this->canUpload($username)) {
            //..Upload file
        }
    }
}
Enter fullscreen mode Exit fullscreen mode

Tadaa! As you can see, Trait's are easily implemented and freely used everywhere you want in your project.

Bad practice

If ever used duplicated methods by implementing multiple Traits, an error will arise. Let's say both Traits have the method canDownload() implemented, PHP wouldn't know which one to use. This is solved by the keyword insteadof:

class File
{
    use Access, Ability{
        Access::canDownload insteadof Ability;
    }

    public function upload(string $username): Response
    {
        if ($this->hasAccess($username) && $this->canUpload($username)) {
            //..Upload file
        }
    }
}
Enter fullscreen mode Exit fullscreen mode

Let me know your experience with Traits and best practices.

Discussion (0)