За последние 24 часа нас посетили 17660 программистов и 1585 роботов. Сейчас ищут 1397 программистов ...

Полиморфные отношения

Тема в разделе "Laravel", создана пользователем Dimon2x, 2 янв 2019.

  1. Dimon2x

    Dimon2x Старожил

    С нами с:
    26 фев 2012
    Сообщения:
    2.210
    Симпатии:
    185
    Сделал по доке One To One (Polymorphic), работает, но пока не въехал, когда это использовать, дайте простые задания, что бы я полностью разобрался именно для One To One (Polymorphic).
     
  2. nospiou

    nospiou Старожил

    С нами с:
    4 фев 2018
    Сообщения:
    3.400
    Симпатии:
    510
    Вынеси аватарку с профиля и картинку с поста в одну таблицу
     
  3. Dimon2x

    Dimon2x Старожил

    С нами с:
    26 фев 2012
    Сообщения:
    2.210
    Симпатии:
    185
  4. nospiou

    nospiou Старожил

    С нами с:
    4 фев 2018
    Сообщения:
    3.400
    Симпатии:
    510
    Что б не создавать много таблиц. У файла помимо пути есть еще и имя и размер возможно геолокацию подцепить захочешь создать миниатюру и т.д видишь сколько уже полей получается. А дальше еще можешь и в коментах захотеть картинки добавлять и еще где то
     
  5. Dimon2x

    Dimon2x Старожил

    С нами с:
    26 фев 2012
    Сообщения:
    2.210
    Симпатии:
    185
    @nospiou то есть поля avatar в таблице users уже не будет?
     
  6. nospiou

    nospiou Старожил

    С нами с:
    4 фев 2018
    Сообщения:
    3.400
    Симпатии:
    510
    @Dimon2x Логично. Вот ты же аватарку режешь? + оригинальное изображение тоже где то хранить нужно соответсвенно уже как минимум 2 поля. Зачем тебе в каждой таблице создавать этих 2 поля если можно все вынести в одну таблицу которая будет отвечать за все файлы.
     
    Dimon2x нравится это.
  7. Dimon2x

    Dimon2x Старожил

    С нами с:
    26 фев 2012
    Сообщения:
    2.210
    Симпатии:
    185
    @nospiou

    @mkramer

    Вот что получилось, правильно ли я вообще думаю?

    модель Post

    PHP:
    1. <?php
    2.  
    3. namespace App;
    4.  
    5. use Illuminate\Database\Eloquent\Model;
    6.  
    7. class Post extends Model
    8. {
    9.      public function image()
    10.     {
    11.         return $this->morphOne('App\Image', 'imageable');
    12.     }
    13. }
    Полиморфная таблица

    555.jpg

    посты

    555.jpg

    Обращаюсь так

    PHP:
    1. $post = Post::find(1);
    2.         $image = $post->image;
    3.    
    4.         dump($post);
    5.         dump(User::find($post->user_id));
    6.         dump($image);
    Выводит коллекцию со статьёй, коллекцию с юзером и коллекцию с этими изображениями и потом я засуну в переменные нужные данные
    и передам их в вид и расставлю изображения в медиазапросы, я правильно понял суть это полиморфной связи?
     
  8. nospiou

    nospiou Старожил

    С нами с:
    4 фев 2018
    Сообщения:
    3.400
    Симпатии:
    510
    Ну то что ты сохраняешь файл с оригинальным названием это не круто. Если появится новая картинка с тем же названием она пере запишет старую. Используй уникальные имена. А оригинальные храни в отдельном поле. На счет медиа запросов ну с таким маленьким интервалом это не нужно миниатюра + оригинал остальное по обстоятельствам.
     
  9. Dimon2x

    Dimon2x Старожил

    С нами с:
    26 фев 2012
    Сообщения:
    2.210
    Симпатии:
    185
    @nospiou название для примера
    --- Добавлено ---
    Но пока так и не понял, когда использовать
     
  10. nospiou

    nospiou Старожил

    С нами с:
    4 фев 2018
    Сообщения:
    3.400
    Симпатии:
    510
    @Dimon2x Если у тебя есть две модели которым нужна таблица (с общими полями). Например комменты могут быть и под аватаркой и под постом. Лайки могут быть и под аватаркой и под постом. И т.д. Все просто.
     
  11. Dimon2x

    Dimon2x Старожил

    С нами с:
    26 фев 2012
    Сообщения:
    2.210
    Симпатии:
    185
    @nospiou Не понял, получается для этого понадобится 2 таблицы с коментами, в одной лежат коменты для аватарки, в другой для поста и в
    полиморфную таблицу в imageable_type указать модель, в imageable_id указать id коммента, а в дополнительные поля что?
     
  12. nospiou

    nospiou Старожил

    С нами с:
    4 фев 2018
    Сообщения:
    3.400
    Симпатии:
    510
    Полиморфные связи используется когда тебе нужна таблица с одинаковой структурой для разных моделей. Притом это не обязательно должно быть 1к1. К примеру аватарка у тебя может быть всего одна (1 к 1) а у поста может быть много картинок (1 к многим) а таблицу ты будешь использовать одну. Вообщем вся суть в том что одна таблица используется для разных моделей ну а что бы можно было различить добавляются два дополнительных поля _id (id модели) и _type (тип модели в ларке по умолчанию это имя класса get_class(User::class) ну или this self внутри модели) но можно переназначит morphMap Не знаю как еще обьяснить.
     
    Dimon2x нравится это.
  13. Dimon2x

    Dimon2x Старожил

    С нами с:
    26 фев 2012
    Сообщения:
    2.210
    Симпатии:
    185
  14. mkramer

    mkramer Суперстар
    Команда форума Модератор

    С нами с:
    20 июн 2012
    Сообщения:
    8.583
    Симпатии:
    1.761
    Ну вот чтобы не надо было две таблицы с комментами, сохраняют тип модели, которая прокомментирована. А разработчики Ларки это дело автоматизировали.

    ну у тебя size-50, size-150, а у них url, чего не ясного-то?
    --- Добавлено ---
    И вместо imagable можно писать какой-нибудь commentable, если нужно. Главное, чтоб всё совпадало, где надо
     
  15. nospiou

    nospiou Старожил

    С нами с:
    4 фев 2018
    Сообщения:
    3.400
    Симпатии:
    510
    Если раньше у тебя было user_id или post_id то сейчас ты используешь общее_название_id (можно не заморачиватся и делать owner_id или model_id в не зависимости от таблицы главное что бы суть передавало) ну и плюс добавляется type (owner_type model_type) больше в структуре различий никаких. А дополнительные поля какие нужны такие и делай.
     
  16. Dimon2x

    Dimon2x Старожил

    С нами с:
    26 фев 2012
    Сообщения:
    2.210
    Симпатии:
    185
    @mkramer но ведь это же всё можно сделать обычными связями многие ко многим
    --- Добавлено ---
    @nospiou то есть полиморфная таблица, это аналог промежуточной?
     
  17. nospiou

    nospiou Старожил

    С нами с:
    4 фев 2018
    Сообщения:
    3.400
    Симпатии:
    510
    Можно. Но тогда поле type нужно будет создавать самому + писать функции для работы а тут уже все готово. Когда ты пишешь $user->image ларка делает get_class($user) и получает тип (ну и соответсвенно добавляет в запрос SELECT WHERE _type=)
    --- Добавлено ---
    Нет. Это обычная таблица как в обычном 1 к 1 или 1 к многим только с полем type)
     
    Dimon2x нравится это.
  18. mkramer

    mkramer Суперстар
    Команда форума Модератор

    С нами с:
    20 июн 2012
    Сообщения:
    8.583
    Симпатии:
    1.761
    Не понял, причём тут многие-ко-многим. Но это и есть обычная связь, только нескольких таблиц с одной. Т.е. и у поста есть картинки, и у пользователя есть картинка, и у комментариев могут быть картинки, к примеру. А чтобы разобраться, какая картинка поста, какая пользователя, какая комментария, вводится дополнительное поле. Если писать самому, то туда даже не обязательно имя класса фигачить. Можно каким-либо другой признак. Но конкретно при Active Record (а Eloquent - это Active Record) удобно писать имя класса. Я когда-то сам до такой схемы с комментариями дошёл, сделал наработки на Yii2, где из коробки нету. В Laravel вот добавили из коробки, причём, недавно, насколько мне известно.
     
    Dimon2x нравится это.
  19. Dimon2x

    Dimon2x Старожил

    С нами с:
    26 фев 2012
    Сообщения:
    2.210
    Симпатии:
    185
    Как вывести посты разных моделей у которых 1 общий тег?

    Имеются модели изображения, видео, теги.

    Для тегов использовал полиморфные связи (Many To Many (Polymorphic)) всё по доке.

    PHP:
    1. class Tag extends Model
    2. {
    3.      public function images()
    4.     {
    5.         return $this->morphedByMany('App\Image', 'taggable');
    6.     }
    7.    
    8.     public function videos()
    9.     {
    10.         return $this->morphedByMany('App\Video', 'taggable');
    11.     }
    12. }
    Пробую вывести пока так

    PHP:
    1.  $tag = Tag::find(1);
    2.        
    3.         foreach ($tag->images as $image) {
    4.             dump($image);
    5.         }
    6.        
    7.         foreach ($tag->videos as $video) {
    8.             dump($video);
    9.         }
    Но этот вариант мне не нравится, как можно сделать одним циклом?

    Или вывести двумя циклами и объединить коллекции?
     
  20. mkramer

    mkramer Суперстар
    Команда форума Модератор

    С нами с:
    20 июн 2012
    Сообщения:
    8.583
    Симпатии:
    1.761
    Ну объединить-то не сложно, что-то типа
    PHP:
    1. $commonCollection = $tag->images->union($tag->videos);
     
  21. Dimon2x

    Dimon2x Старожил

    С нами с:
    26 фев 2012
    Сообщения:
    2.210
    Симпатии:
    185
    @mkramer а вообще так делают, что выводят метки для разных моделей?
     
  22. mkramer

    mkramer Суперстар
    Команда форума Модератор

    С нами с:
    20 июн 2012
    Сообщения:
    8.583
    Симпатии:
    1.761
    А конкретно какая задача? Вывести все модели, связанные с меткой в любом порядке? Или какая-нибудь пагинация предполагается? Смотришь задачу, придумываешь решение.
     
  23. Dimon2x

    Dimon2x Старожил

    С нами с:
    26 фев 2012
    Сообщения:
    2.210
    Симпатии:
    185
    @mkramer Вывести все модели, связанные с меткой и с пагинацией.
     
  24. mkramer

    mkramer Суперстар
    Команда форума Модератор

    С нами с:
    20 июн 2012
    Сообщения:
    8.583
    Симпатии:
    1.761
    Ну вот если с пагинацией, и потенциально этих связей трындецки много, то Laravel уже не помощник (хотя, может @romach или @nosopiu меня поправят), и надо руками сначала запрашивать таблицу тэгов, а потом выделять модели и запрашивать их.
     
  25. MRSgiba

    MRSgiba Активный пользователь

    С нами с:
    22 дек 2017
    Сообщения:
    200
    Симпатии:
    32
    @Dimon2x, Простой (по моему мнению) пример использования полиморфных отношений: номер телефона в организации может быть закреплен:
    1. либо за сотрудником (Иванов Иван - менеджер, который сидит на попе ровно на протяжении долгого времени и не хочет увольняться, и где он сидит нам не важно, для чистоты примера)
    2. либо за местом (например Пост охраны 1 или 2 этажа - где постоянная текучка кадров, и сотрудника конкретного закрепить не получается, да это и не к чему, и не мы решаем кому там сидеть а охранное предприятие, главное не кто там сидит, а где этот Пост).
    Тут мы связываем две разные модели сотрудник, место с моделью номер.