如何使用 Eloquent ::with 方法获取嵌套关系数据库特定列?

How can I get a nested relationship database specific columns with Eloquent ::with method?

我有以下 3 个表格:

posts<--(hasMany)--users--(hasOne)-->user_info

-------------------------------------------------
                     Post
-------------------------------------------------
id | user_id | content | created_at | updated_at
----------------------------------------------------------------------------------------
                                           users
----------------------------------------------------------------------------------------
id | user_info_id | email| username | password | access_token | created_at | updated_at
------------------------------------------------------------------------------------------------------------
                                                      user_info
------------------------------------------------------------------------------------------------------------
id | user_id | name | web | birthday | gender | bio_description | profile_picture | created_at | updated_at

建立的关系如下:

User.php

...
    public function userInfo() {
        return $this->hasOne('App\UserInfo');
    }
...
    public function posts() {
        return $this->hasMany('App\Post');
    }
...

UserInfo.php

...
    public function user() {
        return $this->belongsTo('App\User');
    }
...

Post.php

...
    public function user() {
        return $this->belongsTo('App\User');
    }
...

然后我得到了用户的所有帖子和 user_info 嵌套数据,如下所示:

Post::with('user.userInfo')

其中 returns 是这样的:

{
    "data": [
        {
            "id": 1,
            "created_at": "2020-08-01 06:10:00",
            "updated_at": "2020-08-01 06:10:00",
            "user_id": 1,
            "content": "My first post!",
            "user": {
                "id": 1,
                "user_info_id": 1,
                "email": "myemail@gmail.com",
                "username": "derek",
                "access_token": "secret",
                "created_at": "2020-08-01 04:15:09",
                "updated_at": "2020-08-01 04:15:09",
                "user_info": {
                    "id": 1,
                    "user_id": 1,
                    "name": "Derek Baker",
                    "web": "https://github.com/derek90",
                    "birthday": "1990-11-27",
                    "gender": "M",
                    "bio_description": "Software Developer",
                    "profile_picture": null
                }
            }
        },
        {
            "id": 2,
            "created_at": "2020-08-01 06:09:54",
            "updated_at": "2020-08-01 06:09:54",
            "user_id": 1,
            "content": "My second post!",
            "user": {
                "id": 1,
                "user_info_id": 1,
                "email": "myemail@gmail.com",
                "username": "derek",
                "remember_token": null,
                "access_token": "secret",
                "created_at": "2020-08-01 04:15:09",
                "updated_at": "2020-08-01 04:15:09",
                "user_info": {
                    "id": 1,
                    "user_id": 1,
                    "name": "Derek Baker",
                    "web": "https://github.com/derek90",
                    "birthday": "1990-11-27",
                    "gender": "M",
                    "bio_description": "Software Developer",
                    "profile_picture": null
                }
            }
        }
    ]
}

我想要的是只获取每个实体的几列,如下所示:

{
    "data": [
        {
            "id": 1,
            "created_at": "2020-08-01 06:10:00",
            "updated_at": "2020-08-01 06:10:00",
            "content": "My first post!",
            "user": {
                "id": 1,
                "username": "derek",
                "user_info": {
                    "name": "Derek Baker",
                    "profile_picture": null
                }
            }
        },
        {
            "id": 2,
            "created_at": "2020-08-01 06:09:54",
            "updated_at": "2020-08-01 06:09:54",
            "content": "My second post!",
            "user": {
                "id": 1,
                "username": "derek",
                "user_info": {
                    "name": "Derek Baker",
                    "profile_picture": null
                }
            }
        }
    ]
}

有没有办法使用 Post::with Eloquent 函数实现此目的?

我已经尝试过 Post::with('user:id,username', 'user.userInfo'),它对用户列很有效,但 userInfo 带来了它的全部。

我尝试过的其他事情:

Post::with('user:id,username', 'user.userInfo:name,profile_picture')"user_info": null 带入 json 字段

Post::with('user:id,username', 'user.userInfo:userInfo.name,userInfo.profile_picture') 显示错误 Unknown column 'userInfo.name' in 'field list'

使用user.userInfo:user.userInfo.name,user.userInfo.profile_pictureuser.userInfo:user.user_info.name,user.user_info.profile_picture

会抛出同样的错误

您可以使用 API 资源 https://laravel.com/docs/7.x/eloquent-resources#introduction

API Resource acts as a transformation layer that sits between your Eloquent models and the JSON responses that are actually returned to your application's users.

您可以为 post 创建一个 API 资源,并在响应中 returning post 的任何地方使用它。

Api 资源给了你更多的控制权,你可以操纵你想要的任何字段,使用几个字段的组合发送一些额外的字段,更改你想要在响应中的字段的名称(xyz => $this->name)

PostResource

<?php

namespace App\Http\Resources;

use Illuminate\Http\Resources\Json\JsonResource;

class PostResource extends JsonResource
{
    public function toArray($request)
    {
        //You can access model properties directly using $this

        return [
            "id" => $this->id,
            "created_at" => $this->created_at,
            "updated_at" => $this->updated_at,
            "content" => $this->content,
            "user" => [
                "id" => $this->user->id,
                "username" => $this->user->username,
                "user_info" => [
                    "name" => $this->user->userInfo->name,
                    "profile_picture" => $this->user->userInfo->profile_picture,
                ]
            ]
        ];
    }
}

然后在任何你想要的地方return一个post作为回应。

控制器

// $post is a Post Model Instance.

return new PostResource($post); 

万一你有 collection

// $posts is a collection of Post Model instances.

return PostResource::collection($posts);

PostResource 将应用于您 collection 中的每个模型实例,然后 return 作为您的 JSON 响应发送给您。

[注意]

您可以为用户和任何模型创建类似的资源。它使您可以更轻松地根据需要自定义响应。

还有,在上面的例子中。您可以简单地将 user_info 属性添加到用户,而不是在用户内部使用 user_info。

        return [
            "id" => $this->id,
            "created_at" => $this->created_at,
            "updated_at" => $this->updated_at,
            "content" => $this->content,
            "user" => [
                "id" => $this->user->id,
                "username" => $this->user->username,
                "name" => $this->user->userInfo->name,
                "profile_picture" => $this->user->userInfo->profile_picture,
            ]
        ];