首页 > 解决方案 > Laravel Eloquent 多态模型

问题描述

我遇到了一种情况,我需要一个 Eloquent 模型来动态地合成一个特定的类,该类扩展了我的“正常”雄辩模型。这是一个基于典型电子设备的通用布局:

数据对象:

['id', 'model_type', 'name', 'serial',...]

如果数据都在一个表中(MySQL),Laravel 并没有办法直接将这些数据作为多态提取。您可以对关系进行多态化,但不能直接对模型进行多态化。

本质上,这样做的原因是分离可能与一种类型有关的逻辑,但与另一种类型无关。例如,Model Type AandModel Type B都可以实现一个描述其能力的接口,但 A 的特定逻辑不需要污染 B。

标签: phplaraveleloquentpolymorphism

解决方案


我的解决方案是覆盖newFromBuilder模型上的方法(Laravel 5.6)。像这样:

应用\方案\基础方案

abstract class BaseScheme extends Electronic
{
    // abstract methods to implement
    // ...
}

App\Schemes\ElectronicTypeA

class ElectronicTypeA extends BaseScheme
{
    // Electronic Type A logic
}

App\Schemes\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)进行交互。


推荐阅读