我遇到了一个情况,我需要一个Eloquent模型来动态地融入一个特定的类,扩展我的“普通”雄辩模型。这是一个基于典型电子设备的通用布局:
数据对象:
['id', 'model_type', 'name', 'serial',...]
如果数据全部在一个表(MySQL)中,Laravel实际上没有办法直接将这些数据作为多态转换。您可以将关系变为多态,但不能直接模型化。
基本上,对此的推理是将可能与某种类型有关的逻辑分开,而不是另一种类型。例如,Model Type A
和Model Type B
都可以实现描述其功能的接口,但A的特定逻辑不需要污染B。
答案 0 :(得分:3)
我的解决方案是覆盖模型上的newFromBuilder
方法(Laravel 5.6)。像这样:
应用\方案\ BaseScheme
abstract class BaseScheme extends Electronic
{
// abstract methods to implement
// ...
}
应用\方案\ ElectronicTypeA
class ElectronicTypeA extends BaseScheme
{
// Electronic Type A logic
}
应用\方案\ ElectronicTypeB
class ElectronicTypeB extends BaseScheme
{
// Electronic Type B logic
}
应用\模型\电子
use Illuminate\Database\Eloquent\Model;
class Electornic extends Model
{
public function newFromBuilder($attributes = [], $connection = null)
{
if (!class_exists($attributes->model_type)) {
throw new \Exception("Invalid Scheme ({$attributes->model_type})");
}
$class = $attributes->model_type;
$model = new $class;
if (!$model instanceof \App\Schemes\BaseScheme) {
throw new \Exception("Scheme class is invalid ({$attributes->model_type})");
}
$model->exists = true;
$model->setRawAttributes((array) $attributes, true);
$model->setConnection($connection ?: $this->getConnectionName());
$model->fireModelEvent('retrieved', false);
return $model;
}
其中\App\Schemes\BaseScheme
是抽象,所有逻辑模型都扩展。 \App\Schemes\BaseScheme
还扩展了原始的Eloquent模型。
关于这个的真的很好的事情是它也适用于返回的集合。因此,您可以与模型进行交互,就像它是一个普通模型一样 - 但您真正与特定类(typeA,typeB)进行交互。
答案 1 :(得分:0)
有解决方案。
您可以使用此库: Parental
composer require "calebporzio/parental=0.9"
并使用The Trait扩展子模型。 然后,您可以制作一个Laravel Scope来查询子模型。 这是一个示例:
//parent model
class RoleUser extends Model{
}
以及子模型:
class Expert extends RoleUser
{
use \Parental\HasParent;
public static function boot()
{
parent::boot();
static::addGlobalScope("role", function ($query) {
$query->where("role_type", "App\Expert");
});
}
}