php-traits-laravel-5-1

Uno de los pilares de la programación orientada a objetos es la jerarquía, en la cual podemos hablar de la herencia simple y la herencia múltiple. La herencia es un mecanismo que nos permite crear una clase a partir de la definición de una (herencia simple) o varias (herencia múltiple) ya existentes. Sin embargo, muchos de los lenguajes de programación no soportan la herencia múltiple. PHP es uno de ellos, es decir que con este lenguaje si queremos obtener las propiedades y métodos de una clase para crear una nueva clase solamente lo podemos hacer de una única clase.

Pero trabajar con herencia múltiple nos da ventajas en cuanto a reutilización de código y por tanto, para solventar ese problema a partir de la versión PHP 5.4 se agregó un mecanismo que nos permite emular la herencia múltiple: Traits.

Según la documentación de PHP:

Los traits (rasgos) son un mecanismo de reutilización de código en lenguajes de herencia simple, como PHP. El objetivo de un trait es el de reducir las limitaciones propias de la herencia simple permitiendo que los desarrolladores reutilicen a voluntad conjuntos de métodos sobre varias clases independientes y pertenecientes a clases jerárquicas distintas. La semántica a la hora combinar Traits y clases se define de tal manera que reduzca su complejidad y se eviten los problemas típicos asociados a la herencia múltiple y a los Mixins.

Características de los traits

  • Es similar a una clase, pero con el único objetivo de agrupar funcionalidades muy específicas y de una manera coherente.
  • No se puede instanciar directamente un Trait.
  • Habilita la composición horizontal de comportamientos, es decir, permite reusar código sin tener que usar herencia y así evitando los problemas de duplicidad para clases que tienen los mismos comportamientos pero no pueden derivarse de una única clase padre.
  • El orden de precedencia para la sobreescritura los miembros de la clase actual sobrescriben los métodos del Trait, que a su vez sobrescribe los métodos heredados.
  • Se pueden insertar múltiples Traits en una clase, mediante una lista separada por comas en la sentencia use .

Crear y usar un trait

Los traits son creados usando la palabra clave trait  de esta manera:

trait miTrait {
    public function miMetodo()
    {
	return 'Este es el resultado de miMetodo de miTrait';
    }
}

Luego para usar el trait en todas aquellas clases que queramos trabajar con los métodos o propiedades definidos en el trait, haciendo uso de la palabra clave use  así:

class miClase 
{
    use miTrait;
}

Por tanto, podemos usar el método del trait al crear una instancia de una clase en particular,

$clase = new miClase();
$clase->miMetodo();

o dentro de la clase misma:

class miClase 
{
    use miTrait;

    public function metodoClase()
    {
	$this->miMetodo();
    }
}

Nota: debemos tener presente el namespace del Trait al usarlo en una clase en particular.

El framework Laravel usa Traits frecuentemente para reusar código, los traits disponibles son:

No solo los usa para proveer de funcionalidades a clases del mismo framework, como por ejemplo los traits ValidatesRequestDispatchesJobs y AuthorizesRequests que se utilizan en el controlador base App\Http\Controllers\Controller para agregarle métodos que permitan validar datos según un conjunto de reglas, construir colas de trabajo y autorizar una acción dada, respectivamente.

<?php
namespace App\Http\Controllers;

use Illuminate\Foundation\Bus\DispatchesJobs;
use Illuminate\Routing\Controller as BaseController;
use Illuminate\Foundation\Validation\ValidatesRequests;
use Illuminate\Foundation\Auth\Access\AuthorizesRequests;

class Controller extends BaseController
{
    use AuthorizesRequests, DispatchesJobs, ValidatesRequests;
}

Sino que también esos mismos traits los podemos usar en el desarrollo de nuestras aplicaciones como por ejemplo el trait Illuminate\Database\Eloquent\SoftDelete que nos permite que en un modelo sus registros no se eliminen totalmente de la base de datos sino que usa el atributo deleted_at para establecer que un registro está eliminado, esto se conoce como «soft delete». Podemos usar esta característica en un modelo agregando el trait al archivo del modelo, por ejemplo para trabajar con el modelo Post de un blog. Creamos el modelo y la migración:

php artisan make:model Post -m

Abrimos el archivo de la migración create_posts_table.php ubicado en database/migrations y agregamos, los atributos title, content y deleted_at:

public function up()
    {
        Schema::create('posts', function (Blueprint $table) {
            $table->increments('id');
            $table->string('title');
            $table->text('content');
            $table->softDeletes();
            $table->timestamps();
        });
    }

Con el helper softDeletes() se crea el atributo deleted_at en la tabla posts de la base de datos.

Además modificando el archivo del modelo Post.php en el directorio app para añadir el trait:

<?php

namespace App;

use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\SoftDeletes;

class Post extends Model
{
    use SoftDeletes;

    protected $dates = ['deleted_at'];
}

Además, se agrega deleted_at al array $dates para que pueda ser mutado como fecha. Para conocer más: “Date Mutators” con Eloquent en Laravel 5.1

Incluso hay traits con los que podemos extender las funcionalidades de Laravel, tal es el caso del trait Illuminate\Support\Traits\Macroable  que permite proveer a las clases los métodos con los que podemos crear macros o funciones personalizadas. Dicho trait es usado en:

  • Illuminate/Routing/ResponseFactory.php
  • Illuminate/Routing/Router.php
  • Illuminate/Routing/UrlGenerator.php
  • Illuminate/Support/Arr.php
  • Illuminate/Support/Str.php
  • Illuminate/Filesystem/Filesystem.php
  • Illuminate/Cache/Repository.php
  • Illuminate/Database/Query/Builder.php
  • Illuminate/Support/Collection.php

Es decir, que este trait permite que podamos a través de un service provider extender fácilmente, por ejemplo las  colecciones, para agregarle nuevos métodos adaptados a nuestros proyectos.

Un ejemplo, puede ser añadir un método a las colecciones para convertir sus elementos en mayúsculas, creando un service provider por consola:

php artisan make:provider CollectionMacroServiceProvider

Ahora agregando en el método boot del service provider CollectionMacroServiceProvider, que se encuentra en app/Providers:

<?php

namespace App\Providers;

use Illuminate\Support\Collection;
use Illuminate\Support\ServiceProvider;

class CollectionMacroServiceProvider extends ServiceProvider
{
    /**
     * Bootstrap the application services.
     *
     * @return void
     */
    public function boot()
    {
        Collection::macro('mayusculas', function()
        {
            return collect($this->items)->map(function($word) {
                return strtoupper($word);
            });
        });
    }

    public function register()
    {

    }
}

Luego de registrarlo, agregando al array $providers del archivo app/config.php: App\Providers\CollectionMacroServiceProvider::class,  ya podemos usar nuestro nuevo método con las colecciones, por ejemplo:

En el archivo app/Http/routes.php:

Route::get('/', function () {

	$collection = collect(['name' => 'Desk', 'price' => 100]);
	return $collection->mayusculas();
});

el cual al visitar la ruta nos devuelve:

{"name":"DESK","price":100}

Por tanto, con los PHP traits tenemos un mundo de posibilidades en nuestros proyectos, no solo usando los presentes en el framework de Laravel sino los que podemos crear para extenderlos y así adaptarlos a las necesidades que tengamos. Espero que les haya gustado y les sea de mucha utilidad.

Material relacionado

Regístrate hoy en Styde y obtén acceso a todo nuestro contenido.

Lección anterior Encriptar datos en Laravel Lección siguiente Registro de actividad con Laravel logging