bootstrap - laravel notifications example
Herencia modelo en Laravel (4)
Nota: no puede usar una clase abstracta directamente, tiene que ser extendida por una clase hija
Si su modelo de Tool
( abstract
) no tiene ninguna table
asignada a ella, entonces no necesita usar Tool::all
y no puede usar / instanciar directamente un modelo abstract
, pero puede usar ese modelo abstract
como una clase base como esta:
abstract class Tool extends Eloquent {
protected $validator = null;
protected $errors = null;
protected $rules = array();
// Declare common methods here that
// will be used by both child models, for example:
public static function boot()
{
parent::boot();
static::saving(function($model)
{
if(!$this->isvalid($model->toArray(), $this->rules) return false;
});
}
protected function isvalid($inputs, $rules)
{
// return true/false
$this->validator = Validator::make($inputs, $rules);
if($this->validator->passes()) return true;
else {
$this->errors = $this->validator->errors();
return false;
}
}
public function getErrors()
{
return $this->errors;
}
public function hasErrors()
{
return count($this->errors);
}
// declare any abstract method (method header only)
// that every child model needs to implement individually
}
class Hammer extends Tool {
protected $table = ''hammers'';
protected $fillable = array(...);
protected $rules = array(...); // Declare own rules
}
class Screwdriver extends Tool {
protected $table = ''screwdrivers'';
protected $fillable = array(...);
protected $rules = array(...); // Declare own rules
}
Use Hammer
y Screwdriver
directamente, pero nunca el modelo / clase de la Tool
porque es una clase abstract
, por ejemplo:
$hammers = Hammer:all();
O tal vez algo como esto:
$screwdriver = Screwdriver:create(Input::all());
if($screwdrivers->hasErrors()) {
return Redirect::back()->withInput()->withErrors($screwdriver->getErrors());
}
return Redirect::route(''Screwdriver.index'');
Actualmente estoy trabajando con Laravel y estoy luchando con el hecho de que cada modelo debe extenderse desde Eloquent y no estoy seguro de cómo implementar una Jerarquía de modelos (con diferentes tablas)
Por ejemplo:
Digamos que tengo una Tool
modelo abstracta, y luego un Hammer
modelo y un Screwdriver
modelo que se extienden desde la herramienta.
Ahora, Tool extendería Eloquent ... PERO, no hay NINGUNA Tabla para Herramientas, hay una tabla para Martillos y otra Tabla para Destornilladores, porque tienen atributos diferentes.
¿Cómo especifico que Hammer tiene una tabla y un Destornillador tiene una tabla cuando ambos extienden la Herramienta? ¿Y cómo puedo usar Eloquent para llamar, por ejemplo, todas las herramientas?
Me gusta:
Tools::all()
Esto debería traer todos los martillos y destornilladores porque son todas herramientas.
¿Es esto posible usar Eloquent?
Aunque me gusta el enfoque de relaciones polimórficas (PR) un poco mejor que el de herencia de tabla única ( STI ), todavía no se siente nada como un enfoque de herencia verdadera. Desde el punto de vista del dominio (p. Ej., Un Diagrama de clases UML), es como tratar de usar una relación de composición en lugar de una herencia.
Desde el punto de vista de la coherencia de la base de datos, la relación polimórfica por sí misma ya es una solución muy extraña en Laravel (IMHO). Como no puede haber un solo campo que sea una clave externa para varias tablas, esto puede llevar a unir las ID que no deberían unirse. Y relaciones inversas que no se obedecen.
Aunque en realidad no estoy describiendo una solución al problema, propondría un enfoque diferente al de PR e ITS. Esta solución sería similar al enfoque de tabla por subclase de Hibernate . Creo que la extensión de Dauce a Eloquent va en la misma dirección, excepto que parece que todavía hay algunos problemas de implementación.
Desde el punto de vista de la base de datos, una tabla por subclase también significaría que la superclase contiene una columna por subclase directa. Luego, puede poner restricciones de clave foránea en los identificadores (no nulos) y usar adecuadamente las relaciones. Sin embargo, todavía debería haber alguna lógica adicional en la clase Eloquent mágica de Laravel que convierte el objeto solicitado en el tipo correcto.
Así que para mí, funcionalmente, los modelos Eloquent deberían heredar adecuadamente en el lado de PHP, mientras que la base de datos aún puede usar las restricciones de clave externa.
El único ORM en PHP que conozco que hace una tabla por jerarquía de clases es Doctrine. http://docs.doctrine-project.org/projects/doctrine-orm/en/latest/reference/inheritance-mapping.html . Y creo que puede asignar este tipo de jerarquía que planea usar, una superclase abstracta que puede acceder a todas las subclases.
Para integrar Doctrine to Laravel, sugiero usar el paquete laravel-doctrine, el cual tiene toda la información necesaria en este sitio web http://www.laraveldoctrine.org/ .
Encontré un error (¿característica?) Donde Laravel 5 busca la clase incorrecta si ParentClass y ChildClass tienen la misma cadena $ table. Entonces, si llama a ParentClass :: all () en ciertas situaciones, ¡puede devolver instancias de ChildClass en la colección!
La respuesta del Alfa me llevó a una solución donde crea la siguiente estructura de clase:
abstract class BaseClass extends BaseModel
{
// ParentClass member variables and functions go here, to be shared between parent and child classes
}
class ParentClass extends BaseClass
{
protected $table = ''your_table'';
// place no other member variables or functions in this class
}
class ChildClass extends BaseClass
{
protected $table = ''your_table'';
// ChildClass member variables and functions go here
}
Esto parece forzar a Laravel a hacer la búsqueda correcta cuando llama a ParentClass :: all () o ChildClass :: all () ya que su ancestro común no tiene una tabla declarada. Simplemente trate a BaseObject como ParentObject y de esa manera no tendrá que enturbiar su concepto de herencia con detalles de la base de datos que no deberían ser relevantes. Todavía no he probado el estrés en este tema a fondo, así que asegúrese de anotar la razón de la existencia de esta clase en su código para futuras depuraciones.