Why and How to Make Traits in Laravel

Using Custom Console Commands

Subscribe to my newsletter and never miss my upcoming articles

Listen to this article

One of my favorite PHP features to use in my Laravel projects is Traits. Traits enable you to inherit multiple behaviors in PHP OOP since PHP only allows classes to inherit from one parent. I'm about to show you one of my favorite ways in which I implement them.

The Why:

  • Traits provide a very easy way for code reuse in PHP applications.
  • You can use traits pretty much anywhere in your application where you use classes.
  • Static methods are supported. Usually, when using Traits, you'll initialize them by placing use TraitName; in the class (usually on top). However, you can create your trait methods statically, so you can save a line and use your trait methods, eg. TraitName::method().
  • Abstract methods are supported.

The How: There's no default Artisan command to create Traits in Laravel, so you'll have to create them manually. It's as simple as creating MyTrait.php in app/Traits, and setting the namespace to namespace App\Traits. However, this can be a pain if you're creating multiple Traits, so I'll show you how I automate Trait creation.

  • Create your command by running $ php artisan make:command MakeTrait. This will create a file in app/Console/Commands/.
  • Create a stub, which is the file template that will be used to create the Trait, by running $ php artisan stub:publish.
    • This will create a Stubs/ folder in your root with a bunch of stub files. Create a new trait.stub file and make it look like this:
<?php

namespace App\Traits;

trait {{trait_name}} 
{
    /**
    * Create regular or static methods here
    */
}
  • You'll need to make a few changes to your new MakeTrait command file. Instead of extending Command, you'll be extending GeneratorCommand. Also, you'll want to delete the __construct() and handle() methods since you're not going to need them.
<?php

namespace App\Console\Commands;

use Illuminate\Console\GeneratorCommand;

class MakeTrait extends GeneratorCommand
{
    /**
     * The name and signature of the console command.
     *
     * @var string
     */
    protected $signature = 'command:name';

    /**
     * The console command description.
     *
     * @var string
     */
    protected $description = 'Command description';
}
  • For your $signature property, make it equal to 'make:trait {name};.
  • For your $description property, make it equal to 'Create a new Trait.';
  • Add a new $type property and let it be equal to 'Trait'. This property is used to tell you if the class type has been successfully created or if it already exists.
  • Add a getStub() method to retrieve your stub. Also, make a getDefaultNamespace() method that will get the default namespace for the class.
  • Finally, add a replaceClass($stub, $name) that will override the method that's in GeneratorCommand so that Laravel knows what to do with {{trait_name}}. Usually, it will look for DummyCommand or {{class}}. So in all, your command should look like this:
<?php

namespace App\Console\Commands;

use Illuminate\Console\GeneratorCommand;

class MakeTrait extends GeneratorCommand
{
    /**
     * The name and signature of the console command.
     *
     * @var string
     */
    protected $signature = 'make:trait {name}';

    /**
     * The console command description.
     *
     * @var string
     */
    protected $description = 'Create a new Trait.';

    protected $type = 'Trait';

    protected function getStub(){
        return base_path('stubs/trait.stub');
    }

    protected function getDefaultNamespace($rootNamespace){
        return $rootNamespace . '\Traits';
    }

    protected function replaceClass($stub, $name){
        $class = str_replace($this->getNamespace($name).'\\', '', $name);

        return str_replace('{{trait_name}}', $class, $stub);
    }
}
  • Now create a new trait by running $ php artisan make:trait FooBarTrait. You'll see your new Trait in app/Traits.

Conclusion:

  • In app/Console you will see a Kernel.php file. There's a property there called $commands where you can place the path for a command that may not be found by Laravel. By default, it will look directly in the Commands folder, as you may see in the commands() method below.
  • One Trait that I always make in my projects is a DayTimeTrait. In a future article, I'll show you an advanced usage with Rules.

No Comments Yet