Laravel雄辩的混合模型集合

时间:2019-11-10 12:27:15

标签: laravel eloquent laravel-6

我有一个数据库,其中有一个称为文件的表。其中,我们具有以下结构-

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

然后我有两个模型,一个叫做File,另一个叫做FolderFolder扩展了File。例如,当我调用File::all(),时,是否可以利用Eloquent来基于数据库type字段映射各个模型?

2 个答案:

答案 0 :(得分:1)

雄辩的返回集合实例,所以一种方法是调用map()并让它返回每个项目的相应对象,例如,如果是文件,则仅返回文件,而如果是文件夹,则填充新的Folder实例并返回它。

或者您可以让FileFolder成为在同一表上工作的模型,并使用全局范围来限制按类型设置的查询,然后在两者上调用all()并合并它们。

但是我认为最好的办法是使它们成为单个模型,并根据类型表现不同。在模型上的方法中放置任何不同的功能,以便通过调用这些方法将其视为相同的类型,而不管其类型如何。我认为这是比较安全的选择,因为您可以使模型变为多态模型-无论类型如何,都可以将它们视为相同。

答案 1 :(得分:0)

我已经能够通过扩展Laravel模型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枚举的类型返回Foldertype模型实例。

感谢大家的投入!