Laravel Eloquent коллекция смешанных моделей - PullRequest
0 голосов
/ 10 ноября 2019

У меня есть база данных с таблицей файлов. В рамках этого у нас есть следующая структура -

- id
- parent_id (nullable)
- name
- type (enum: File or Folder)
- created_at
- updated_at

У меня есть две модели, одна называется File, а другая - Folder. Folder расширяется File. Есть ли способ, когда я звоню, например, File::all(),, я могу использовать Eloquent для сопоставления соответствующих моделей на основе поля type базы данных?

Ответы [ 2 ]

1 голос
/ 10 ноября 2019

Eloquent возвращает экземпляры коллекции, поэтому одним из способов было бы вызвать map() и получить, чтобы они возвращали соответствующие объекты для каждого элемента, например, если это файл, просто возвращайте файл, тогда как если это папка, заполните новую * 1002. * экземпляр и вернуть его.

Или у вас могут быть File и Folder модели, работающие на одной и той же таблице, с глобальными областями действия, используемыми для ограничения набора запросов по типу, затем вызовите all() onоба из них и объединить их.

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

0 голосов
/ 10 ноября 2019

Я смог выработать ответ, расширив метод Laravel Models newFromBuilder.

Вот мой класс -

class File {

    public static $types = ['File', 'Folder'];

     /**
     * Create a new model instance that is existing.
     *
     * @param array $attributes
     * @param null  $connection
     *
     * @return Model|string
     */
    public function newFromBuilder($attributes = [], $connection = null)
    {
        $model = $this->newInstanceFromType($attributes->type);

        $model->exists = true;

        $model->setRawAttributes((array) $attributes, true);

        $model->setConnection($connection ?: $this->getConnectionName());

        $model->fireModelEvent('retrieved', false);

        return $model;
    }

    /**
     * Determine our model instance based on the type field.
     *
     * @param string $type
     *
     * @return mixed
     */
    private function newInstanceFromType(string $type)
    {
        if (!in_array($type, static::$types)) {
            throw new InvalidArgumentException('$type must be one of static::$types');
        }

        $model = 'App\Models\\' . $type;
        return new $model;
    }
}

Это вернет либо File или Folder экземпляр модели в зависимости от того, что перечисление type из базы данных.

Спасибо всем за ввод!

...