【问题标题】:Laravel - dynamic Eloquent Model depending on column valueLaravel - 取决于列值的动态 Eloquent 模型
【发布时间】:2016-12-02 15:52:32
【问题描述】:

在我的数据库中,我有一个表form_fields,其结构如下:

id  | form_id | title   | type
1   | 1       | Subject | text
2   | 1       | Enquiry | textarea
3   | 1       | Logo    | file

我有FormFormField 模型,与Form 有这样的关系:

public function fields()
{
    return $this->hasMany('App\Modules\Forms\Models\FormField', 'form_id', 'id');
}

现在可以根据type 字段更改使用哪个类吗?因此,如果我有TextFormFieldTextareaFormFieldFileFormField,都扩展了基础FormField 模型,是否有可能让Laravel 使用它们?还是我必须手动完成,所以获取字段,遍历它们,然后根据类型创建新实例?哪个看起来不难,但是好像很浪费资源,好像我有20个字段,会创建20个FormField实例,然后我再手动创建20个?

谢谢!

【问题讨论】:

    标签: php laravel eloquent


    【解决方案1】:

    在关系中,你不能,因为当你访问你的字段时

    foreach($form->fields as $field) { ... }
    

    你已经通过$this->hasMany(...),它已经消失了,你不能为每个字段提供不同的类。

    您可以做的是在获得对象后将其重新转换为适当的类,执行以下操作:

    这是一个工作示例

    Route::get('debug/cast', function () {
        $form = collect([['type' => 'text', 'name' => 'address'], ['type' => 'date', 'name' => 'birthdate']]);
    
        $fields = FieldTypeCollection::make($form->toArray());
    
        dd($fields);
    });
    
    class FieldTypeCollection extends Collection
    {
        public function __construct($items)
        {
            parent::__construct($items);
    
            if (is_array($items)) {
                $this->recastAll();
            }
        }
    
        private function recastAll()
        {
            $items = [];
    
            foreach ($this->items as $key => $item) {
                $items[] = (new FieldFactory())->make($item);
            };
    
            $this->items = $items;
        }
    }
    
    class FieldFactory
    {
        public function make($field)
        {
            if ($field['type'] == 'date') {
                $new = new DateInputFieldType();
            } else {
                $new = new TextInputFieldType();
            }
    
            return $this->importData($field, $new);
        }
    
        private function importData($old, $new)
        {
            $new->type = $old['type'];
    
            $new->name = $old['name'];
    
            return $new;
        }
    }
    
    class TextInputFieldType
    {
        public $type;
    
        public $name;
    }
    
    class DateInputFieldType
    {
        public $type;
    
        public $name;
    }
    

    你会得到这个结果:

    【讨论】:

    • 重写模型的 get 方法不是更容易吗,例如 (psuedocode) function get(){return SomeClassname::where(type, classId)}->get();
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-08-04
    • 2020-01-08
    相关资源
    最近更新 更多