Laravel по-русски

Русское сообщество разработки на PHP-фреймворке Laravel.

Ты не вошёл. Вход тут.

#1 23.01.2021 08:53:44

i3bepb
Откуда: Екатеринбург
Сообщений: 20

Как сделать полиморфную связь на одну и туже таблицу

Есть 2 таблицы - таблица картинок и таблица связи картинки с картинкой.

Например заливаем картинку, делаем запись о ней в первую таблицу, затем делаем для нее thumbnail это тоже картинка пишем о ней также в первую таблицу, теперь надо знать, что на первую оригинальную картинку есть thumbnail и они связываются под средством второй таблицы. Также в дальнейшем оригинальная картинка еще может обрабатываться и на выходе получатся оптимизированный вариант, также она может перегоняться в формат pdf, т.е. получается на 1 оригинальную картинку в итоге получается несколько других связанных с оригинальной.

Таблица files

Column        |              Type              |      Description
--------------+--------------------------------+------------------------
 id           | bigint                         |
 path         | character varying(512)         | Путь до файла
 created_at   | timestamp(0) without time zone |

Таблица file_file_assoc

  Column   |          Type          |                                                     Description
-----------+------------------------+----------------------------------------------------------------------------------------------------------
 parent_id | bigint                 | id оригинального изображения
 child_id  | bigint                 | id thumbnail, оптимизированного или pdf изображения
 file_type | character varying(255) | Указывает на то чем является child_id файл по отношению к parent_id - миниатюра, склеенный pdf, оптимизированный
Indexes:
    "file_file_assoc_pkey" PRIMARY KEY, btree (parent_id, file_type)

Пример данных:

  id  |                                   path              |     created_at
------+-----------------------------------------------------+---------------------
 2015 | /api/file/20/12/14/0007/2012140007_15.jpeg          | 2021-01-22 22:38:17
 2016 | /api/file/20/12/14/0007/2012140007_01.jpeg          | 2021-01-22 23:12:55
 2022 | /api/file/20/12/14/0007/opt/2012140007_15.jpeg      | 2021-01-22 23:23:50
 2023 | /api/file/20/12/14/0007/opt/2012140007_01.jpeg      | 2021-01-22 23:27:28
 2024 | /api/file/20/12/14/0007/thumbnail/2012140007_02.jpg | 2021-01-22 23:36:30
 2025 | /api/file/20/12/14/0007/thumbnail/2012140007_03.jpg | 2021-01-22 23:42:37

 parent_id | child_id | file_type
-----------+----------+-----------
      2015 |     2022 | optimized
      2016 |     2023 | optimized
      2015 |     2024 | thumbnail
      2016 |     2025 | thumbnail

Есть модель File:

namespace App\Models;
class File extends Model
{

    public function thumbnail()
    {
        return $this->morphToMany(
            self::class,
            'file',
            'file_file_assoc',
            'parent_id',
            'child_id',
            'id',
            'id'
        );
    }

    public function optimized()
    {
         ...
    }
}

Т.е. например для картинки (id=2017) чтобы выбрать thumbnail нужен подобный запрос:

SELECT files.*
FROM file_file_assoc
    JOIN files ON files.id = file_file_assoc.child_id
WHERE file_file_assoc.parent_id = 2017 and file_file_assoc.file_type = 'thumbnail';

А для выбора optimized, тоже самое только меняется file_type.

Как мне описать relation thumbnail() и optimized(), чтобы была возможность подобного выбора миниатюр, оптимизированных вариантов и т.д. ? Т.е. как мне получить это через ORM ? Я вижу, что это похоже на https://laravel.com/docs/master/eloquen … ationships, но как конкретно это сделать!?

Не в сети

#2 31.01.2021 18:57:13

i3bepb
Откуда: Екатеринбург
Сообщений: 20

Re: Как сделать полиморфную связь на одну и туже таблицу

Вообще я нашел решение, еще 24.01.2021. Вот тут https://laravel.com/docs/8.x/eloquent-r … phic-types есть описание как сделать типы кастомными и предлагается как вариант разместить их в App\Providers\AppServiceProvider, дак вот их можно также разместить динамически в каждый из методов thumbnail(), optimized() и .т.д. Т.е получится примерно такое:

namespace App\Models;
use Illuminate\Database\Eloquent\Relations\Relation;
class File extends Model
{

    public function thumbnail()
    {
        Relation::morphMap([
            'thumbnail' => 'App\Models\File',
        ]);
        return $this->morphToMany(
            self::class,
            'file',
            'file_file_assoc',
            'parent_id',
            'child_id',
            'id',
            'id'
        );
    }

    public function optimized()
    {
        Relation::morphMap([
            'optimized' => 'App\Models\File',
        ]);
         ...
    }
}

Не в сети

Подвал раздела