Полиморфные отношения Ларавеля позволяют модели принадлежать более чем одной другой модели в одной ассоциации. Для этого урока мы возьмем официальный пример документации Laravel. Возьмем пример «комментариев» как в постах, так и в видео. Используя полиморфные связи, можно использовать одну таблицу комментариев для обоих этих сценариев.
По умолчанию Laravel будет использовать полное имя класса для хранения типа связанной модели.
Существует четыре типа полиморфных отношений в Laravel.
- One To One Polymorphic Relationship
- One To Many Polymorphic Relationship
- Many To Many Polymorphic Relationship
- Custom Polymorphic Relationship
Полиморфные отношения
один к одномуПолиморфное отношение «взаимно-однозначное» сравнимо с простым взаимно-однозначным отношением; Однако целевая модель может принадлежать нескольким типам моделей в одной ассоциации.
Например, запись блога и пользователь могут иметь полиморфное отношение к модели изображения.
Использование взаимно-однозначного полиморфного отношения позволяет получить единый список уникальных изображений, которые принимаются как для записей блога, так и для учетных записей пользователей.
Полиморфные отношения
«один ко многим»Полиморфное отношение «один ко многим» сравнимо с простым отношением «один ко многим»; Однако целевая модель может принадлежать нескольким типам моделей в одной ассоциации.
Например, представьте, что пользователи вашего приложения могут «комментировать» как публикации, так и видео.
Используя полиморфные отношения, вы можете использовать таблицу с одним комментарием для обоих этих вариантов использования.
Полиморфные отношения
«многие ко многим»Полиморфные отношения «многие-ко-многим» несколько сложнее, чем отношения morphOne и morphMulti.
Например, модель Blog Post и Video может иметь полиморфное отношение к модели Tag.
Используя полиморфное отношение «многие-ко-многим», у вас есть единый список уникальных тегов, общих для записей блога и видео.
Пользовательские полиморфные отношения
Например, учитывая приведенный выше пример «один ко многим», где комментарий может принадлежать публикации или видео, commentable_type по умолчанию будет App\Post или App\Video соответственно.
Тем не менее, вы можете позавидовать, если отделите свою базу данных от внутренней структуры вашего приложения.
В этом случае вы можете установить «карту морфов», чтобы указать Eloquent использовать пользовательское имя для каждой модели вместо имени класса.
Теперь давайте возьмем общий пример полиморфных отношений.
Всего есть три таблицы.
- posts
- videos
- comments
Причина, по которой мы можем применить здесь полиморфные отношения, заключается в том, что комментарии можно применять как к сообщениям, так и к видео.
Таким образом, модель комментариев может быть связана с постом и видео.
Теперь нам нужно добавить два дополнительных столбца в таблицу сообщений .
- commentable_id (Integer)
- commentable_type (String)
В столбце commentable_id будет указано значение идентификатора поста или видео.
Столбец commentable_type будет содержать имя класса модели-владельца. Теперь давайте начнем практику на примере полиморфных отношений Laravel.
Мы начинаем наш проект с установки проекта Laravel.
Шаг 1: Установите Laravel 6
Введите следующую команду в терминале.
laravel new relationships
# или
composer create-project laravel/laravel relationships --prefer-dist
После установки заходим в проект.
cd relationships
Откройте проект в редакторе кода.
code .
Настройте базу данных в файле .env .
Теперь создайте шаблон проверки подлинности с помощью следующей команды.
php artisan make:auth
Шаг 2: Создание моделей и миграция.
Перейдите в свой терминал и сначала создайте модель Post .
php artisan make:model Post -m
Кроме того, мы создаем видеомодель .
php artisan make:model Video -m
Теперь определите схему для обеих миграций. Но сначала давайте определим схему для create_posts_table.
// create_posts_table
public function up()
{
Schema::create('posts', function (Blueprint $table) {
$table->increments('id');
$table->string('name');
$table->timestamps();
});
}
Теперь определите схему для create_videos_table.
// create_videos_table
public function up()
{
Schema::create('videos', function (Blueprint $table) {
$table->increments('id');
$table->string('name');
$table->timestamps();
});
}
Хорошо, теперь мигрируйте с помощью следующей команды.
php artisan migrate
Шаг 3: Создайте два файла контроллера.
Хорошо, теперь мы создадим два контроллера для рендеринга представлений.
- PostController
- VideoController
Введите следующую команду, чтобы создать его.
php artisan make:controller PostController
php artisan make:controller VideoController
Теперь напишите следующий код внутри файла PostController.php .
// PostController.php
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use App\Post;
class PostController extends Controller
{
public function show(Post $post)
{
return view('post.show', compact('post'));
}
}
То же самое и с файлом VideoController.php .
// VideoController.php
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use App\Video;
class VideoController extends Controller
{
public function show(Video $video)
{
return view('video.show', compact('video'));
}
}
Теперь создайте две папки внутри папки views .
- post
- video
Внутри папки post создайте новый файл с именем show.blade.php файл. Кроме того, то же самое создает тот же файл show.blade.php внутри папки с видео .
Шаг 4: Определите маршруты для показа поста и видео.
Внутри файла web.php напишите следующий код.
// web.php
Route::get('/post/{post}', 'PostController@show')->name('post.show');
Route::get('/video/{video}', 'VideoController@show')->name('video.show');
Теперь введите данные вручную в базу данных. В режиме реального времени данные поступают из формы, но для этой демонстрации сначала введите некоторые фиктивные данные в таблицу сообщений .
Теперь вставьте данные в таблицу видео .
Итак, мы вставили фиктивные данные в обе таблицы.
Шаг 5: Закодируйте файлы просмотра.
Внутри post >> файле show.blade.php напишите следующий код.
<h3>{{ $post->name }}</h3>
Теперь перейдите в браузер и введите этот URL-адрес: http://relationships.test/post/1. Вы можете увидеть 1-й пост.
То же самое для видео >> show.blade.php напишите следующий код.
<h3>{{ $video->name }}</h3>
То же самое, зайдите в браузер и нажмите на этот URL-адрес: http://relationships.test/video/1. Вы можете посмотреть 1-е видео.
Шаг 6: Создайте модель комментариев.
Введите следующую команду, чтобы создать модель, а также выполнить миграцию.
php artisan make:model Comment -m
Теперь напишите следующую схему внутри create_comments_table.
// create_comments_table
public function up()
{
Schema::create('comments', function (Blueprint $table) {
$table->increments('id');
$table->integer('user_id')->unsigned();
$table->text('body');
$table->integer('commentable_id')->unsigned();
$table->string('commentable_type');
$table->timestamps();
});
}
Перенесите эту схему в базу данных.
php artisan migrate
Шаг 7: Определите отношения.
Теперь мы храним user_id внутри таблицы комментариев ; у нас есть отношения с Пользователем.
Комментарий принадлежит пользователю. Таким образом, мы можем записать эту связь внутри файла модели Comment.php.
// Comment.php
public function user()
{
return $this->belongsTo(User::class);
}
Хорошо, теперь мы пишем еще одну функцию внутри файла Comment.php , которая является commentable().
// Comment.php
public function commentable()
{
return $this->morphTo();
}
Теперь это означает, что теперь одна или несколько моделей могут использовать эту модель комментариев. В нашем примере он может быть связан с постом и видео. Оба используют одну и ту же модель комментариев .
Итак, следующий шаг - модель поста имеет много комментариев. Таким образом, мы можем определить отношения внутри файла Post.php следующим образом.
// Post.php
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class Post extends Model
{
public function comments()
{
return $this->morphMany(Comment::class, 'commentable');
}
}
То же самое и с файлом Video.php .
// Video.php
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class Video extends Model
{
public function comments()
{
return $this->morphMany(Comment::class, 'commentable');
}
}
Шаг 8: Вставьте ручные данные в таблицу комментариев.
Мы наладили все отношения. Нам нужно ввести демонстрационные комментарии и посмотреть, получим ли мы комментарии на странице шоу видео и поста.
Так, первый столбец – это id, как обычно, автоприращения, второй – user_id, который в данный момент подписан пользователем.
Третий столбец — commentable_id; в нашем случае это либо идентификатор таблицы сообщений , либо идентификатор таблицы видео .
Итак, мы прикрепили посты и таблицы видео к соответствующим комментариям.
Теперь визуализируйте сообщение с их комментариями в файле show.blade.php .
<h3>{{ $post->name }}</h3>
<ul>
@foreach($post->comments as $comment)
<li>{{ $comment->body }}</li>
@endforeach
</ul>
Зайдите в браузер и нажмите на этот URL-адрес: http://relationships.test/post/1. Вы можете увидеть название сообщения и тело комментария. Вы можете написать тот же файл представления для видео >> show.blade.php.
<h3>{{ $video->name }}</h3>
<ul>
@foreach($video->comments as $comment)
<li>{{ $comment->body }}</li>
@endforeach
</ul>
Теперь проверьте этот URL-адрес: http://relationships.test/video/1.
Вот и все; Мы успешно отобразили пост и видео с соответствующими комментариями.
Хотя в этом примере я вставил значения жесткого кода, но мы увидим программно в будущем.