A simple guide to using Traits in Laravel 5

a simple guide to using traits in laravel 5

Overview

If you have exposure to Object Oriented programming, then you will have been introduced to the concept of abstract classes and interfaces. A “Trait” is similar to an abstract class, in that it cannot be instantiated on its own but contains methods that can be used in a concrete class. Traits were introduced in PHP in version 5.4 and are used extensively in the Laravel Framework. They are ideal in reducing the limiting effect of single inheritance, thus enabling the exposing of methods as if they were defined in the calling class. The exact definition from the PHP site defines Traits as such:

“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.”

Example File

Creating a Trait is just like defining a class, the following simple example (excluding comments) shows a single file with one trait which has 2 methods:

<?php namespace AppTraits;

trait ExampleCode
{
    public function printThis()
    {
        echo "Trait executed";
        dd($this);
    }

    public function anotherMethod()
    {
        echo "Trait – anotherMethod() executed";
    }
}

Our example looks just like a class definition, except we use the keyword “trait”, there is no constructor as it cannot be instantiated (just like an abstract class). It uses a name space of AppTraits to give it a clear grouping (you can use anything you like here). If you need to access code in other name spaces then just include the “use” statement (see example below) and create and call the method(s) as needed.

Within the file, function names must be unique and if they do conflict with existing methods then the following precedence takes effect:

  1. An inherited member from a base class is overridden by a member inserted by a Trait.
  2. Members from the current class override Trait methods.

Storing Traits

For convenience I created a directory under “app” called “Traits”, and placed my custom PHP files there. Each file uses the name of the Trait for logical correlation. By using a name space of “AppTraits” in each file the Framework was able to locate my files when I “use” them in another file.

Sample Usage Code:

<?php
/**
 * class AdminLoginJob
 * @date 2016-11-03
 */
namespace AppJobs;

use AppJobsJob;
use IlluminateContractsBusSelfHandling;

use AppTraitsExampleCode;

/**
 *  brief Example code using a Trait in a Laravel "Job"
 */
class AdminLoginJob extends Job implements SelfHandling
{
    use ExampleCode;
    
    /**
     * Call trait to print something. Note the use of "$this".
     * 
     * @return void
     */
    public function __construct()
    {
        $this->printThis();
    }

   /**
     * Do more stuff here.
     * 
     * @return void
     */
     public function handle()
    {
        // never gets called in this example.
    }
}

The printThis() method is in our trait and accessed using $this-> notation just as if it was in the Class file. Multiple traits can be used in this manor, just select names carefully.

Laravel 5.8 Working Example

Since the release of the original article, Laravel has evolved and some of the syntax has changed. Below is a fully working example, with code.

To kick it off, add a route to your routes file for a GET call to the controller, mine looks like this:

Route::get( ‘/example’,’Example@Example’);

app/Traits/ExampleCode.php

This is the actual Trait we will use in the example. It has two methods, for this example we will just use the first one “printThis()”.

<?php 
 namespace App\Traits;
 trait ExampleCode
 {
     public function printThis()     
     {               
         echo "Trait executed";    
         dd($this);           
     }
     public function anotherMethod()
     {
         echo "Trait - anotherMethod() executed";
     }
 }   

app/Jobs/ExampleJob.php

In our example, we have attached the Trait to a Job, you could use it anywhere but in this example we will dispatch a job and call the Trait code.

<?php
 /**
 \class ExampleJob
 @date 2019-07-31
 */
 namespace App\Jobs; 
 use App\Jobs\Job;
 use App\Traits\ExampleCode;
 /**
 \brief Example code using a Trait in a Laravel "Job"
 */
 class ExampleJob extends Job
 {
 use ExampleCode; 
 /**
 Call trait to print something. Note the use of "$this".
 *
 @return void
 */
 public function __construct()
 {
     $this->printThis();
 }
 public function handle()
 {
     // never gets called in this example.
 }
 } 

app/Http/Controllers/Example.php

Our controller is the entry point for the route and its sole purpose is to dispatch the Job.

<?php
 namespace App\Http\Controllers;
 use App\Http\Controllers\Controller;
 use App\Jobs\ExampleJob;
 class Example extends Controller
 {
     public function __construct()
     {
     }
     public function Example()
     {
         dispatch(new ExampleJob());
     }
 }

Browser Output

Web Browser output:

Trait executed
ExampleJob {#458 ▼
+connection: null
+queue: null
+chainConnection: null
+chainQueue: null
+delay: null
+chained: []
}

Yep! – that’s it a working example with the Trait attached to a Job being dispatched from a Controller in this example.

Documenting Traits with Doxygen

I think code documentation is critical, so it pays to make an effort to insert formatted comments that can be collected by a suitable tool and generated onto a web site for easy access. I tend to CRON my document generation, so as code is edited and saved new comments and code appear in the reports. Another handy feature is leaving TODO notes so code can be revisited to introduce new functionality. To achieve this I use Doxygen as my main tool but also run phpDocumentor2 and phpDox over the code, this given me lots of useful info in different formats.

By default Doxygen does not support PHP Traits in its documentation output, however several StackExchange posts cover a workaround:

Related posts:

Manual Page on input Filters:

Enjoy!

-oOo-
 

Back to the Blog

avatar of sid young

Sid Young

  • Conetix
  • Conetix

Let's Get Started

  • This field is for validation purposes and should be left unchanged.