Как реализовать одиночное наследование таблиц с помощью Larvel’s Eloquent?

В настоящее время у меня есть модель classа 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 . Каков наилучший способ сделать это и с чего начать?

Прежде чем я перейду в наследование нескольких таблиц, я хочу потерять несколько слов об одном наследовании таблицы . Наследование отдельных таблиц – это более простой способ, когда дело доходит до наследования с помощью моделей db.
У вас есть несколько моделей, привязанных к одной таблице и столбцу type чтобы различать разные classы моделей. Однако причина, по которой вы обычно хотите реализовать наследование, заключается в том, что модели имеют общие свойства, а также некоторые, которые являются уникальными для модели.
При использовании однонаправленного наследования таблица выглядит примерно так:

 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 . Тип говорит нам, в какой таблице мы найдем наш «rest» модели, а id указывает первичный ключ принадлежащей ему записи. Обратите внимание, что имена столбцов могут быть любыми, что вы хотите, но условно назвать его «-able» .

Давайте взглянем на модели 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); 

Итак, как вы можете видеть, чистая firebase database поставляется с ее ценой. С вашей моделью будет немного сложнее. Однако вы можете поместить всю эту дополнительную логику (например, необходимую для создания модели) в функцию вашего модельного classа и не беспокоиться об этом слишком много.

Кроме того, есть хороший учебник для многостраничного наследования с laravel. Может быть, это помогает;)

от Laravel 5.2, доступен Global Scope :

 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' добавляется ко всем запросам Article же, как SoftDeletes .

 >>> App\Article::where('id', 1)->toSql() => "select * from `posts` where `id` = ? and `type` = ?" 

На самом деле laravel предоставляет свойство SoftDeletes используя эту функцию.

Interesting Posts

Открытие книги Excel 2003 в Excel 2010 32-бит вызывает ложную циркулярную ссылку и сбои

Как найти версию JVM из программы?

Резервное копирование загрузочного / системного раздела

Экспортировать электронную таблицу Excel в текстовый файл с фиксированной шириной?

Видео YouTube не воспроизводится в WebView – Android

Как приложения Meteor могут работать в автономном режиме?

Нужно ли вручную дефрагментировать компьютер под управлением Windows 7?

Как установить include path в проект xcode

IIS 7.5 + включить PUT и DELETE для службы RESTFul, без расширения

Функциональное программирование против объектно-ориентированного программирования

Какова максимальная температура, которую могут достичь мои процессоры до причинения ущерба?

ПодготовленоСодержание с Statement.RETURN_GENERATED_KEYS

Передача данных на главную страницу в ASP.NET MVC

Отключить «Вы хотите изменить цветовую схему для повышения производительности?»

ipad safari: отключить прокрутку и эффект отскока?

Давайте будем гением компьютера.