mysql - crear - ¿Cómo puedo implementar la herencia de una sola tabla usando Laravel''s Eloquent?
crear trait laravel (2)
de Laravel 5.2, Global Scope
está disponible:
class Article extends Post
{
protected $table = ''posts'';
protected static function boot()
{
parent::boot();
static::addGlobalScope(''article'', function (Builder $builder) {
$builder->where(''type'', ''article'');
});
}
}
where type = ''article''
se agrega a todas las consultas de Article
como SoftDeletes
.
>>> App/Article::where(''id'', 1)->toSql()
=> "select * from `posts` where `id` = ? and `type` = ?"
En realidad, laravel proporciona el rasgo de SoftDeletes
usando esta característica.
Actualmente tengo una clase modelo llamada Post
.
class Post extends Eloquent {
protected $table = ''posts'';
protected $fillable = array(''user_id'', ''title'', ''description'', ''views'');
/*
* Relationships
*/
public function user()
{
return $this->belongsTo(''User'');
}
public function tags()
{
return $this->belongsToMany(''Tag'', ''post_tags'');
}
public function reactions()
{
return $this->hasMany(''Reaction'');
}
public function votes()
{
return $this->hasMany(''PostVote'');
}
//Scopes and functions...
}
Me gustaría dividir publicaciones en dos tipos diferentes; articles
y questions
. Pensé que la mejor manera de hacerlo es por herencia, por lo que Article
y Question
ampliarían Post
. ¿Cuál es la mejor manera de hacer esto y por dónde empezar?
Antes de profundizar en la herencia de tablas múltiples , quiero perder algunas palabras sobre la herencia de tablas únicas . La herencia de tablas únicas es la forma más fácil cuando se trata de herencia con modelos db.
Tiene varios modelos vinculados a la misma tabla y una columna de type
para distinguir entre las diferentes clases de modelo. Sin embargo, la razón por la que normalmente desea implementar la herencia es porque los modelos tienen propiedades compartidas, pero también algunas que son exclusivas del modelo.
Al usar la herencia de tabla única, su tabla se ve similar a la que en algún momento:
id shared_column question_column article_column question_column2 article_column2 etc...
1 Lorem 62 NULL test NULL
2 Ipsum NULL x NULL true
Terminas teniendo muchos valores NULL porque no se necesitan columnas para cierto tipo de modelo. Y con muchos registros, esto puede influir en el tamaño de la base de datos.
Sin embargo, en algunos casos, podría ser la mejor solución. Aquí hay un tutorial bien escrito que muestra cómo implementarlo en Laravel de una manera bastante elegante.
Herencia de tabla múltiple
Ahora veamos la herencia de tablas múltiples. Con este método, divide su única tabla en varias (bueno, supongo que el nombre ya dio ese tipo de distancia;)) Vamos a utilizar una técnica llamada Polimorfismo
Nuestro esquema del ejemplo anterior se vería así:
posts table:
id shared_column postable_id postable_type
1 Lorem 1 Question
2 Ipsum 1 Article
questions table:
id question_column question_column2
1 62 test
articles table:
id article_column article_column2
1 x true
Mucho más limpio si me preguntas ...
Las columnas interesantes aquí son postable_id
y postable_type
. El tipo nos dice en qué tabla encontraremos nuestro "resto" del modelo y el ID especifica la clave principal del registro que le pertenece. Tenga en cuenta que los nombres de las columnas pueden ser lo que usted desee, pero es una convención llamarlo "-able" .
Echemos un vistazo a los modelos Eloquent ahora.
Enviar
class Post extends Eloquent {
// all your existing code
public function postable(){
return $this->morphTo();
}
}
Pregunta / Artículo / cualquier otro tipo postable
class Question extends Post {
public function post(){
return $this->morphOne(''Post'', ''postable'');
}
}
Tenga en cuenta que en realidad no tiene que extender desde la Post
pero puede hacerlo si tal vez tiene métodos que desea utilizar también. De todos modos, la relación polimórfica funcionará con o sin ella.
Ok, esa es la configuración básica. A continuación, le mostramos cómo puede usar sus nuevos modelos:
Recuperar todas las publicaciones
$posts = Post::all();
Recuperar todas las preguntas
$questions = Question::all();
Obtener columnas de preguntas de una publicación
$post = Post::find(1);
$question_column2 = $post->postable->question_column2;
Obtener propiedades de publicación de la pregunta
$question = Question::find(1);
$shared_column = $question->post->shared_column;
Compruebe qué tipo es una publicación
$post = Post::find(1);
echo ''type: ''.get_class($post->postable);
if($post->postable instanceof Question){
// Looks like we got a question here
}
Crear una nueva pregunta
Ahora tengan paciencia conmigo, crear un modelo es un poco más complicado. Si tiene que hacerlo en varios lugares de su aplicación, le sugiero que escriba una función reutilizable para ello.
// create a record in the questions and posts table
$question = new Question();
$question->question_column = ''test'';
$question->save();
$post = new Post();
$post->shared_column = ''New Question Post'';
$post->save();
// link them together
$question->post()->save($post);
Como puede ver, una base de datos limpia viene con su precio. Será un poco más complejo manejar su modelo. Sin embargo, puede poner toda esta lógica extra (por ejemplo, la necesaria para crear un modelo) en una función en su clase de modelo y no se preocupe demasiado por ello.
Además, hay un buen tutorial para la herencia de tablas múltiples con laravel también. Tal vez ayuda;)