首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Laravel策略类设计模式->多态关系

Laravel策略类设计模式->多态关系
EN

Stack Overflow用户
提问于 2021-03-17 14:54:57
回答 1查看 257关注 0票数 1

在Laravel实现这一目标的最佳方法是什么?我之所以特别提到拉拉维尔,是因为我对拉勒维尔还很陌生。我正在尝试在其中实现它,我确信Laravel有一个我还不熟悉的方面,它可以很好地解决这个问题。

让我用一个简单的例子来说明:

原始设计

假设您有一个汽车模型:

代码语言:javascript
复制
class Car extends Model
{
    protected $fillable = [
        'manufacturer',
        'model',
        'engine', //json field emulating a table
    ]
}

非规范化的“engine”字符串字段包含json。json将始终具有一个“type”属性,但从那里开始,它将向各个方向发展。示例(使用我对汽车发动机的不完全知识):

  • { "type": "petrol", "attributes":{"base_engine_type":"V-8", "size":"5.7L"...} }
  • { "type": "electric", "attributes":{"battery":"Lithium-Ion", "charge_period_hours":"20"...} }
  • { "type": "steam", "attributes":{"pressure_bar":"300", "spontanious_steampunk_world_transport_percent":"42"...} }等等。

用例

汽车模型将有一个Vue页面,其中包含各种发动机类型的下拉列表。在选择时,将显示特定于引擎类型及其各自属性的组件.

我的解决方案

  1. 保持原样

我使用引擎JsonResource来模拟控制器和页面之间的通信模型。

  1. 一个具有动态添加属性的单个引擎模型,然后将其注入Car模型。我只是推测过这个。构造函数中添加的属性没有反映。但它的主旨是:
代码语言:javascript
复制
class Engine extends Model
{
    public function __construct(array $attributes=[])
    {
        parent::__construct($attributes);

        foreach ($this->attributes()->get() as $attr) {
            $name = $attr->name;

            $this->append($name)->$name = $attr->value;
            $this->fillable[] = $name;
        }
    }

    public function attributes() {
        return $this->hasMany(EngineAttribute::class);
    }
}

class EngineAttribute extends Model
{
    protected $fillable = [
        'name',
        'value',
    ];
}

,木头和树,

第一种解决方案目前效果最好,但违反了1NF,并且没有适当的可伸缩性。第二个解决方案在应用程序中引入了可怕的复杂性,我宁愿避免它。

建议,替代解决方案,建议修改我的问题,或一般照明将不胜感激。

(编辑:修正了JSON示例)

更新

再次感谢你的回答,伙计。但是我看到了你的拉拉维尔风格,我用更多的拉拉维尔风格来抚养你。这是一段艰苦的旅程。充满了奇怪的特征和可怕的枢轴扩展连接模型,由可怕的连接表产生,通过他们真正的类名捕捉许多模型的灵魂。但是我安全地回来了,很幸运的是,我还是完好无损地回来了,给我们带来了这个奖:多态关系,我把这个奇怪的魔法应用到你已经很好的代码上了!它开始转变为:

代码语言:javascript
复制
<?php

class EngineType extends Model {
    public function attributes() 
    {
        return $this->morphMany(
            EngineAttribute::class,
            'attributable'
        );
    }
}

class EngineAttribute extends Model {
    public function attributable()
    {
        return $this->morphTo();
    }
}

class Car extends Model {

    public function engineType() {
        return $this->hasOne(EngineType::class);
    }
}

我上面提到的Ottwell的这本书包含了其他的咒语,但是这个未经检验的炼金术将提供这个想法。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2021-03-23 10:13:24

在我看来,第二个选项更好,它更清晰和可扩展,但是我们可以改进一点,我们可以删除Engine

In风格

代码语言:javascript
复制
class EngineType {
    public $id;
    public $typeName;
}

class EngineAttribute {
    public $cardId;
    public $engineTypeId;
    public $name;
    public $value;
}

class Car {
    public $id;
    public $manufacturer;
    public $model;
    public $engineTypeId;
}

拉拉维尔风格:

代码语言:javascript
复制
class EngineType extends Model {
}

class EngineAttribute extends Model {
}

class Car extends Model {

    public function engineType() {
        return $this->hasOne(EngineType::class);
    }

    public function attributes() {
        return $this->hasManyThrough(EngineAttribute::class, EngineType::class, 'card_id', 'engine_type_id', 'id', 'id');
    }

    public function toJson() {
        return json_encode($this);
    }
}
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/66675590

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档