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 extendingCommand
, you'll be extendingGeneratorCommand
. Also, you'll want to delete the__construct()
andhandle()
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 agetDefaultNamespace()
method that will get the default namespace for the class. - Finally, add a
replaceClass($stub, $name)
that will override the method that's inGeneratorCommand
so that Laravel knows what to do with{{trait_name}}
. Usually, it will look forDummyCommand
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 thecommands()
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.
ย