2016-12-02 4 views
-2

В моей базе данных у меня есть таблица form_fields с такой структурой:Laravel - динамическая Eloquent модель в зависимости от значения столбца

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

И я Form и FormField модели, с такими отношениями с Form:

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

Теперь можно изменить класс, который используется на основе поля type? Так что, если бы у меня были TextFormField, TextareaFormField и FileFormField, все расширяющие основание FormField Модель, можно ли получить Laravel, чтобы использовать их? Или мне нужно сделать это вручную, чтобы получить поля, прокрутить их и создать новые экземпляры на основе типа? Кажется, что это не сложно, но это кажется пустой тратой ресурсов, как будто у меня есть 20 полей, 20 FormField экземпляров будут созданы, а затем я вручную создам еще 20?

Спасибо!

ответ

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; 
} 

Вы получите этот результат :

enter image description here

+0

не было бы easyer переопределить метод GET для чего-то модели, как (psuedoco de) function get() {return SomeClassname :: where (type, classId)} -> get(); –

Смежные вопросы