目前,我有一个名为的模型类Post。
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... }
我想将帖子分为两种不同的类型;articles和questions。我认为做到这一点的最佳方法是通过继承,所以Article并且Question会扩展Post。最佳方法是什么?从哪里开始?
articles
questions
Article
Question
在深入探讨 多表 继承之前,我想谈一谈 单表 继承。当涉及到数据库模型的继承时,单表继承是更简单的方法。 您有多个模型绑定到同一张表,并有一个type列来区分不同的模型类。但是,您通常要实现继承的原因是因为模型具有共享的属性,但也具有模型唯一的属性。 使用单表继承时,您的表在某些时候看起来类似于:
type
id shared_column question_column article_column question_column2 article_column2 etc... 1 Lorem 62 NULL test NULL 2 Ipsum NULL x NULL true
您最终会拥有很多NULL值,因为某些类型的模型不需要某些列。并且由于记录很多,这可能会影响数据库的大小。
但是,在某些情况下,它可能仍然是最佳解决方案。这是一个写得很好的教程,展示了如何以一种非常优雅的方式在Laravel中实现它。
现在让我们看一下多表继承。通过这种方法,您可以将单个表拆分为多个表(好吧,我猜这个名字已经给您了;)我们将使用一种称为多态的技术
上面示例中的架构如下所示:
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
如果你问我,那会更干净…
这里有趣的列是postable_id和postable_type。该类型告诉我们在哪个表上可以找到模型的“其余部分”,并且id指定属于该记录的主键。请注意,列名称可以是您想要的任何名称,但是习惯上称它为 “ -able” 。
postable_id
postable_type
现在让我们看看Eloquent模型。
发布
class Post extends Eloquent { // all your existing code public function postable(){ return $this->morphTo(); } }
问题 / 文章 / 其他可张贴的类型
class Question extends Post { public function post(){ return $this->morphOne('Post', 'postable'); } }
请注意,实际上您不必从扩展,Post但是如果您也有要使用的方法,则可以。无论如何,无论有没有多态关系都可以使用。
好的,这是基本设置。这是使用新模型的方法:
检索所有帖子
$posts = Post::all();
检索所有问题
$questions = Question::all();
从帖子中获取问题列
$post = Post::find(1); $question_column2 = $post->postable->question_column2;
从问题中获取帖子属性
$question = Question::find(1); $shared_column = $question->post->shared_column;
检查帖子是哪种类型
$post = Post::find(1); echo 'type: '.get_class($post->postable); if($post->postable instanceof Question){ // Looks like we got a question here }
提出新问题
现在让我忍受,创建模型要复杂一些。如果必须在应用程序中的多个位置执行此操作,建议您为其编写可重用的函数。
// 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);
因此,您可以看到,干净的数据库附带了价格。处理您的模型会更加复杂。但是,您可以将所有这些额外的逻辑(例如,创建模型所需的所有逻辑)放入模型类的函数中,不必太担心。
另外,还有一个很好的教程,用于使用laravel进行多表继承。也许有帮助;)