2017-01-07 11 views
5

Итак, у меня есть эта сумасшедшая идея, связанная с Laravel и модельным наследованием. Я хотел бы настроить набор моделей с одним родителем, но когда я попрошу дочернюю модель, я хотел бы вернуть данные. Например, я бы Контакты модель, которая является родительской:Laravel 5 Наследование модели - возвращение родительских данных при получении дочернего режима

Contacts: id, first_name, last_name, image

Тогда я бы рядом типов контактов, которые наследуются из списка контактов. Каждая из этих дочерних моделей будет иметь свой собственный набор полей (т. Е. Для членов, которых я должен знать, когда они присоединились, и т. Д., Но для добровольцев мне может потребоваться знать, есть ли у них современный сертификат первой помощи). Вот несколько примеров:

Members: contact_id, joined_on, birthday, medical_concerns 
Volunteers: contact_id, current_first_aid, interests 
Staff: contact_id, pay_rate 

Я хотел бы быть в состоянии сделать что-то вроде:

$members = \App\Member::all();

и имеют контакт и члены возвращаемые данные, как если бы все было один ряд, как это:


+---+------------+-----------+-------+------------+------------+------------------+ 
|id | first_name | last_name | image | joined_on | birthday | medical_concerns | 
+---+------------+-----------+-------+------------+------------+------------------+ 
| 1 | Fred  | Bloggs | null | 2015-01-01 | 1993-10-22 | false   | 
| 2 | Jim  | Phillips | null | 2016-04-30 | 1987-09-22 | true    | 
+---+------------+-----------+-------+------------+------------+------------------+ 

И чтобы сделать это немного сложнее, я хотел бы, чтобы все отношения, которые относятся к родителям, работали для ребенка. Так что я мог бы сделать что-то вроде этого:

$members = \App\Member::find(1)->phone

И, несмотря на то модель член не имеет отношения к определенной модели телефона было бы вернуть телефон, связанный с Контакта, потому что родитель имеет такие отношения.

Я хотел бы также, чтобы иметь возможность указать столбцы, которые не принадлежат к ребенку при получении данных и не Laravel выдаст ошибку:

$members = \App\Member::all(['first_name','last_name','joined_on']) 

Я возился с перекрывая модель Красноречивый и написав мою собственную версию всех и найдя методы, которые работают, но похоже, что мне, возможно, придется переопределить все методы, чтобы заставить это работать, и, возможно, это будет больше работы, чем просто оставить «Красноречивый» и искать другого (или моего собственного на заказ).

Итак, я думаю, мои вопросы: есть ли «легкий» способ сделать это с Laravel или я пытаюсь заставить его делать то, что он никогда не собирался делать?

ответ

0

Я думаю, что вы можете сделать так:

$members = \App\Members::with('contact')->all(); 

Конечно ваша модель Участники должны были определить отношение belongsTo к модели контакта.

0

Is there an "easy" way to do this with Laravel or am I trying to make it do things that it was never intended to do?

Да.

Eloquent не управляет наследованием таким образом. Возможно, было бы лучше реализовать polymorphic relations.

Однако, перекрывая только этот бит, кажется, служит своим целям:

abstract class ContactSubclass extends Contact 
{ 
    protected $with = 'parent'; 

    public function parent() 
    { 
     return $this->belongsTo(Contact::class, 'contact_id'); 
    } 

    public function newQuery() 
    { 
     $contactTable = (new Contact())->getTable(); 
     $thisTable = (new static())->getTable(); 

     $builder = parent::newQuery(); 
     $builder->join($contactTable, "$thisTable.contact_id", '=', "$contactTable.id"); 

     return $builder; 
    } 

    public function newFromBuilder($attributes = [], $connection = null) 
    { 
     $model = parent::newFromBuilder($attributes, $connection); 

     if ($model->parent) { 
      $model->setRawAttributes(array_merge($model->parent->getAttributes(), $model->getAttributes()), true); 
     } 

     return $model; 
    } 

    protected function getRelationshipFromMethod($method) 
    { 
     if (method_exists(parent::class, $method)) { 
      return $this->parent->getRelationshipFromMethod($method); 
     } 

     return parent::getRelationshipFromMethod($method); 
    } 
} 

У Member и другие подклассы расширить этот класс (или добавить эти переопределения в каждом классе, который расширяет Contact).

(Я не проверял его полностью, попробуйте.Кроме того, это не будет обрабатывать прямые нагрузки напрямую; попробуйте найти, что следует отменить, если вы хотите это поддержать.)