Ya vimos en Rimorsoft un artículo completo sobre la herencia, de esa manera extender nuestras clases y compartir funcionalidad. El problema básico con extender extends
clases, es que solo puedes extender de una, solo una. Créeme, esto limita y mucho.
Ejemplo real
<?php
namespace App\Entities;
use App\Classes\Permission;
use Illuminate\Notifications\Notifiable;
use Illuminate\Foundation\Auth\User as Authenticatable;
class User extends Authenticatable
{
use Notifiable, Permission;
// ...
}
Esta es la entidad User
que viene por defecto al instalar Laravel:
Illuminate\Foundation\Auth\User
, y la entidad User
la usa para heredar.¿Este ejemplo que dice realmente? muestra que extendemos de una (1) clase y usamos dos (2) traits.
extends Authenticatable
use Notifiable, Permission;
Es una gran ventaja, un Trait es un código que reutilizamos y podemos incluirlo en cualquier clase... Piensa en esto "código reutilizable"
Definición: Con los traits es posible que nuestras clases de PHP hereden métodos y propiedades. Es la solución directa al problema de herencia única.
<?php
trait TagTrait
{
// ...
}
Un trait se parece mucho a una clase pero aquí usamos la palabra clave trait. No es obligatorio pero podemos seguir la convención de colocar el sufijo Trait en el nombre, ejemplo TagTrait
.
Notas
extends
ni implements
, tampoco puedes crear un objeto a partir de él (no puedes instanciar un trait).<?php
trait TagTrait
{
/**
* @param $tags string or array
*/
public function tags($tags)
{
// Code here
}
/**
* @param $tag string
*/
private function addTag($tag)
{
// Code here
}
// ...
}
Con este simple Trait aislamos toda la lógica sobre las etiquetas Tag
y es la mejor manera de hacerlo, porque así tendremos un único código y el resto de nuestro sistema tendrá la función de etiquetas. De esta manera los usuarios, productos, artículos, etc tendrán la opción de ser segmentados por etiquetas y cada clase solo deberá incluir el archivo TagTrait
.
Es decir, puede la clase User
extender de una clase muy relacionada con ella, lo mismo Product
, Post
y así, pero lo interesante aquí es que pueden todas incluir el Trait TagTrait
.
Recuerda: El sufijo Trait no es obligatorio, es una convención y aquí es muy apropiado usarlo en la explicación
Usa traits para extender y mejorar la funcionalidad de tus clases, esto es todo... Extensión de código, aislar código útil.
Veamos ejemplos: Archivo public/index.php
<?php
require '../vendor/autoload.php';
use App\User;
$user = new User;
echo $user->greet();
Archivo app/User.php
<?php
namespace App;
use App\Traits\Test;
/**
* this class represents a user
*/
class User
{
use Test;
}
Archivo app/Traits/Test.php
<?php
namespace App\Traits;
/**
* this trait represents a Test
*/
trait Test
{
function greet()
{
return "Mi primer Trait";
}
}
La lógica de greet()
está en el archivo Trait llamado Test y User
lo puede usar porque incluye el Trait.
Seguramente te has preguntado ¿Qué pasaría si extendemos de una clase, usamos un trait y ambos tienen un método con el mismo nombre?
Imagina: Mi clase User
extiende, es decir, hereda de la clase Person
y además incluye el trait TagTrait
, entonces, ¿Qué pasa si Person
y TagTrait
tienen un método con el mismo nombre?
La respuesta es: El método del trait tiene prioridad sobre el método de la clase padre. En otras palabras, con los traits podemos reemplazar la funcionalidad heredada.
Otra pregunta ¿Qué pasa si mi clase padre, el Trait y mi clase actual tienen un método con el mismo nombre?, ejemplo:
User
método getName()
Person
método getName()
TagTrait
método getName()
Gana la clase; Se revisa de esta manera: (1) clase, (2) trait, (3) clase padre.
Ejemplo: Archivo public/index.php
<?php
require '../vendor/autoload.php';
use App\User;
$user = new User;
echo $user->greet();
Aquí creamos un objeto y usamos el método greet()
Archivo app/User.php
<?php
namespace App;
use App\Traits\Test;
/**
* this class represents a user
*/
class User extends Person
{
use Test;
function greet()
{
return "Hola, soy la clase User";
}
}
Nuestra clase User
tiene el método greet()
y al mismo tiempo extendemos o heredamos de Person
y ademas hacemos uso del Trait Test.php
Archivo app/Person.php
<?php
namespace App;
/**
* this class represents a person
*/
class Person
{
function greet()
{
return "Hola, soy la clase padre";
}
}
Archivo app/Traits/Test.php
<?php
namespace App\Traits;
/**
* this trait represents a Test
*/
trait Test
{
function greet()
{
return "Hola, soy un Trait";
}
}
Se ve claramente que nuestra clase User
, nuestra clase padre Person
y nuestro trait Test
usan el método greet()
¿Quien gana?
¿Quien gana ahí?, vamos a simplificarlo de la siguiente manera:
En otras palabras, los métodos propios tienen la última palabra
Cuando esto sucede te saldrá un error Fatal
Fatal error: Trait method greet has not been applied, because there are collisions with other trait methods on ... in ... on line 10
Archivo public/index.php
<?php
require '../vendor/autoload.php';
use App\User;
$user = new User;
echo $user->greetOne();
echo '<br>';
echo $user->greetTwo();
Archivo app/User.php
<?php
namespace App;
use App\Traits\TestOne;
use App\Traits\TestTwo;
/**
* this class represents a user
*/
class User
{
use TestOne, TestTwo {
TestOne::greet insteadof TestTwo; // Usa el TestOne en lugar de TestTwo (esto resuelve el conflicto)
TestOne::greet as greetOne; // Usando alias
TestTwo::greet as greetTwo; // Usando alias
}
}
Aquí la clave está en la palabra insteadof
, básicamente traduce a "Usa esta clase en lugar de esta otra"
Archivo app/Traits/TestOne.php
<?php
namespace App\Traits;
/**
* this trait represents a Test
*/
trait TestOne
{
function greet()
{
return "Hola, soy un TraitOne";
}
}
Archivo app/Traits/TestTwo.php
<?php
namespace App\Traits;
/**
* this trait represents a Test
*/
trait TestTwo
{
function greet()
{
return "Hola, soy un TraitTwo";
}
}
Los Traits inyectan flexibilidad, esta es la palabra clave
Repositorio: https://github.com/rimorsoft/Serie-de-PHP/tree/master/trait
Adquiere en preventa y aprovecha un gran descuento TDD en Laravel
Comparte en
el auth de laravel trabaja basado en tokens o con el objeto session de php ...
Buenas a todos, tengo un problema, ultimamente, cada vez que creo un nuevo proyecto de Laravel las rutas de este no funcionan. Por ejemplo: si creo el proyecto, éste se crea, pero al agregarle el sistema de autenticación: "auth" se generan tanto las rutas en el archivo web.php y las vistas. pero si intento acceder a la sección de registro o inicio de sesión me aparece el e...
Hola, tengo una consulta por hacer. Quisiera conocer sus opiniones, sobre como mostrar los errores de validación con ajax cuando utlizo la clase Form Request. Debo decir que el mensaje de registrado con éxito si lo muestra, sin embargo los mensajes de error no los he podido mostrar. Gracias
//FORM REQUEST
public function rules()
{
return [
...
Hola buenas a todos estoy trabajando en un sistema en el cuál, en un formulario tengo un select para seleccionar datos de una tabla, y en la vista del formulario me funciona ya que me carga todos los datos que tengo almacenados en dicha tabla; pero cuando selecciono una de las opciones, sea cual séa la que seleccione, siempre se guarda el primer registro de la tabla... Es com...