Ключевым аспектом создания надежных приложений в Laravel является понимание и эффективное использование различных типов отношений, поддерживаемых Eloquent, собственной ORM Laravel. Eloquent упрощает обработку сложных отношений между моделями, и одним из таких отношений является полиморфное отношение «один ко многим». В этом сообщении блога мы рассмотрим этот конкретный тип отношений и выясним, как он может улучшить ваше моделирование данных в Laravel.

Понимание полиморфных отношений «один ко многим»:

В ситуации, когда пользователи вашего приложения могут «комментировать» несколько объектов, таких как сообщения и видео, полиморфное отношение «один ко многим» предлагает элегантное решение. Вы можете использовать одну таблицу comments для хранения комментариев как к сообщениям, так и к видео. Давайте посмотрим на необходимую структуру таблицы:

posts
    id - integer
    title - string
    body - text
 
videos
    id - integer
    title - string
    url - string
 
comments
    id - integer
    body - text
    commentable_id - integer
    commentable_type - string

Обратите внимание на поля commentable_id и commentable_type в таблице comments. В столбце commentable_id будет храниться идентификатор поста или видео, а в столбце commentable_type будет храниться имя класса родительской модели.

Структуры модели:

Двигаясь вперед, давайте настроим определения модели, необходимые для построения этой связи:

namespace App\Models;
 
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\MorphTo;
 
class Comment extends Model
{
    /**
     * Get the parent commentable model (post or video).
     */
    public function commentable(): MorphTo
    {
        return $this->morphTo();
    }
}

use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\MorphMany;
 
class Post extends Model
{
    /**
     * Get all of the post's comments.
     */
    public function comments(): MorphMany
    {
        return $this->morphMany(Comment::class, 'commentable');
    }
}
 
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\MorphMany;
 
class Video extends Model
{
    /**
     * Get all of the video's comments.
     */
    public function comments(): MorphMany
    {
        return $this->morphMany(Comment::class, 'commentable');
    }
}

Получение отношения:

После определения таблиц и моделей базы данных вы можете получить доступ к отношениям. Например, чтобы получить все комментарии к сообщению, вы можете использовать динамическое свойство comments:

use App\Models\Post;
 
$post = Post::find(1);
 
foreach ($post->comments as $comment) {
    // ...
}

Чтобы получить родителя полиморфной дочерней модели, вы можете получить доступ к методу morphTo. В данном случае это метод commentable модели Comment:

use App\Models\Comment;
 
$comment = Comment::find(1);
 
$commentable = $comment->commentable;

Отношение commentable в модели Comment будет возвращать экземпляр Post или Video, в зависимости от того, какой модели принадлежит комментарий.

Полиморфные отношения «один ко многим» в Laravel предлагают гибкий и элегантный способ установления отношений между различными моделями с использованием одного отношения. Используя эту взаимосвязь, вы можете писать более чистый и удобный для сопровождения код, который в полной мере использует Eloquent ORM Laravel. Не бойтесь использовать эти взаимосвязи, чтобы сделать процесс разработки приложений более плавным и эффективным. Удачного кодирования!