Ответ 1
Прежде чем я перейду на наследование нескольких таблиц, я хочу потерять несколько слов об одном наследовании таблицы. Наследование отдельных таблиц - это более простой способ, когда дело доходит до наследования с помощью моделей db.
У вас есть несколько моделей, привязанных к одной таблице и столбцу 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, потому что для определенного типа моделей не нужны столбцы. И с большим количеством записей это может повлиять на размер базы данных.
Однако в некоторых случаях это может быть лучшим решением. Здесь хорошо написанный Tutorial, который показывает, как реализовать его в 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".
Теперь взглянем на модели Eloquent.
Сообщение
class Post extends Eloquent {
// all your existing code
public function postable(){
return $this->morphTo();
}
}
Вопрос/ Article/ любой другой тип сообщения
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);
Итак, как вы можете видеть, чистая база данных поставляется с ценой. С вашей моделью будет немного сложнее. Однако вы можете поместить всю эту дополнительную логику (например, необходимую для создания модели) в функцию в вашем классе модели и не беспокоиться об этом слишком много.
Кроме того, есть хороший Tutorial для многостраничного наследования с laravel. Может быть, это помогает;)