Laravel 5 Model Inheritance - 获取子模式时返回父数据

Posted

技术标签:

【中文标题】Laravel 5 Model Inheritance - 获取子模式时返回父数据【英文标题】:Laravel 5 Model Inheritance - returning parent data when getting child mode 【发布时间】:2017-05-22 04:06:51 【问题描述】:

所以我有一个与 Laravel 和模型继承有关的疯狂想法。我想配置一组具有单亲的模型,但是当我请求子模型时,我希望返回数据。例如,我会有一个 Contacts 模型,它是父模型:

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

而且,即使 Member 模型没有定义到 Phone 模型的关系,它也会返回与 Contact 相关的电话,因为父模型具有这种关系。

我还希望能够在检索数据时指定不属于子项的列,并且不会让 Laravel 抛出错误:

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

我已经搞砸了重写 Eloquent 模型并编写了我自己的 all 版本并找到了正在工作的方法,但看起来我可能必须重写所有方法才能让它工作,也许这会更多工作不仅仅是放弃 Eloquent 并寻找其他(或我自己定制的)解决方案。

所以我想我的问题是:有没有一种“简单”的方法可以用 Laravel 做到这一点,还是我试图让它做一些它从未打算做的事情?

【问题讨论】:

【参考方案1】:

我认为你可以这样做:

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

当然,您的 Members 模型应该已经定义了与联系模型的 belongsTo 关系。

【讨论】:

【参考方案2】:

有没有一种“简单”的方法可以用 Laravel 做到这一点,还是我试图让它做一些它从未打算做的事情?

是的。

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 的类中添加这些覆盖)。

(我还没有彻底测试过,试一试。另外,这不会直接处理急切的负载;如果你想支持它,请尝试找到要覆盖的内容。)

【讨论】:

以上是关于Laravel 5 Model Inheritance - 获取子模式时返回父数据的主要内容,如果未能解决你的问题,请参考以下文章

Laravel 4 / 5:使`return Model`自动使用HTML视图

Laravel 5.3 $model->save() 值始终为空,但是批量分配有效

Laravel 5 Model Inheritance - 获取子模式时返回父数据

PHPStorm 无法识别 Laravel 5.0 中我的 Model 类的方法 [重复]

Laravel Eloquent Model :: find不起作用

laravel 学习日记(入门 laravel5.5实现简单登陆)