Задать вопрос
deadloop
@deadloop
Активно осваиваю PHP

Обычные vs полиморфные отношения, какие выбрать?

Помогите разобраться в данном вопросе.

Есть четыре модели:

1. Post
2. Category
3. Tag
4. Image

Я хочу связть первые 3 с 4-ой, в данный момент я реализовал через обычне отношения один к одному. У поста, категори и тэга буду одна картинка

Но есть вариант использовать Полиморфные отношения, какой вариант будет наиболее эффективным/удачным для данного случая?

class Post extends Model
{
    public function category()
    {
        return $this->belongsTo(Category::class);
    }

    public function tags()
    {
        return $this->belongsToMany(Tag::class);
    }

    public function image()
    {
        return $this->hasOne(Image::class);
    }
}


class Category extends Model
{
    public function posts()
    {
        return $this->hasMany(Post::class);
    }

    public function image()
    {
        return $this->hasOne(Image::class);
    }
}

class Tag extends Model
{
    public function posts()
    {
        return $this->belongsToMany(Post::class);
    }

    public function image()
    {
        return $this->hasOne(Image::class);
    }
}

class Image extends Model
{
    public function post()
    {
        return $this->belongsTo(Post::class);
    }

    public function category()
    {
        return $this->belongsTo(Category::class);
    }
    
    public function tag()
    {
        return $this->belongsTo(Tag::class);
    }
}
  • Вопрос задан
  • 220 просмотров
Подписаться 2 Простой Комментировать
Решения вопроса 1
@jazzus
Конечно полиморфные. А если 15 сущностей имеют картинку (что запросто может быть) - 15 айдишников прописывать в images, затем 15 belongsTo отношений в модели? Не лучшая идея. Удобней трейт HasImage с отношением morphOne image, подключенный у всех моделей. Единственная "сложность" это контролировать удаление картинки при удалении модели, но тебе итак нужно удалять картинку, как минимум с диска. Зацепить при этом модель одна строчка. В том же трейте HasImage прописал один раз логику в методе deleteImage и там this->image->delete, а сам метод вызывать в обсервере у модели при удалении. И всякие сервисные методы типа получения ссылки на изображение и т.д. Все в одном трейте. Сэкономлена тонна кода. Только в случае картинок я бы сразу сделал много картинок у сущности т.е. morphMany, что не помешает тебе брать одну. Т.к. где morphMany images может быть и morphOne image. А лучше вообще одну таблицу файлов т.к. какая разница какие файлы картинки это или документы - у всех одна логика загрузки, удаления и тд.
Ответ написан
Пригласить эксперта
Ответы на вопрос 2
Sanes
@Sanes
Если устраивают обычные отношения, лучше использовать их. Полиморфные работают только магией laravel. Обычные на уровне базы данных. С другой стороны вам при удалении сущности надо удалять файл. И тут уже без laravel не обойтись.
Ответ написан
Комментировать
Adamos
@Adamos
Ну, если разобраться...
Что такое обычные отношения? Вот у поста есть id, а у фотки есть post_id. Так она приколочена к этому посту.
Что такое полиморфные отношения? Вот у поста есть id и у коммента есть id, а у фотки есть morph_id - в котором хранится, внезапно, все то же значение id поста или коммента, которому она принадлежит. Только, чтобы разобраться, к кому именно, хранится еще и morph_type, в котором прописано, например, имя модели, которая по этой связи будет обращаться: "App\Models\Post" или "App\Models\PostComment".

Довольно очевидно, что если иерархия линейная - есть категории, в них посты, у них фотки - то и разводить полиморфизм тут просто негде.
Ответ написан
Комментировать
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы