我有一个数据库,其中有一个称为文件的表。其中,我们具有以下结构-
- id
- parent_id (nullable)
- name
- type (enum: File or Folder)
- created_at
- updated_at
然后我有两个模型,一个叫做File
,另一个叫做Folder
。 Folder
扩展了File
。例如,当我调用File::all(),
时,是否可以利用Eloquent来基于数据库type
字段映射各个模型?
答案 0 :(得分:1)
雄辩的返回集合实例,所以一种方法是调用map()
并让它返回每个项目的相应对象,例如,如果是文件,则仅返回文件,而如果是文件夹,则填充新的Folder
实例并返回它。
或者您可以让File
和Folder
成为在同一表上工作的模型,并使用全局范围来限制按类型设置的查询,然后在两者上调用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
枚举的类型返回Folder
或type
模型实例。
感谢大家的投入!