【问题标题】:How can I get a nested relationship database specific columns with Eloquent ::with method?如何使用 Eloquent ::with 方法获取嵌套关系数据库特定列?
【发布时间】:2020-11-22 08:30:12
【问题描述】:

我有以下 3 个表:

帖子用户--(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 和 user_info 嵌套数据的帖子,如下所示:

Post::with('user.userInfo')

返回如下内容:

{
    "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') 在 json 字段中带来 "user_info": null

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 会引发相同的错误

【问题讨论】:

    标签: php mysql laravel eloquent lumen


    【解决方案1】:

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

    API 资源充当转换层,位于您的 Eloquent 模型和实际返回的 JSON 响应 您的应用程序的用户。

    您可以为帖子创建 API 资源,并在响应中返回帖子的任何地方使用它。

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

    发布资源

    <?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,
                    ]
                ]
            ];
        }
    }
    

    然后无论您想在哪里回复帖子。

    控制器

    // $post is a Post Model Instance.
    
    return new PostResource($post); 
    

    如果你有收藏

    // $posts is a collection of Post Model instances.
    
    return PostResource::collection($posts);
    

    PostResource 将应用于您集合中的每个模型实例,然后作为您的 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,
                ]
            ];
    
    
    
    

    【讨论】:

    • 有趣。谢谢。我正在尝试应用此解决方案,但我必须弄清楚如何使它与订购结果一起工作。 (我有的是Post::with('user:id,username', 'user.userInfo')-&gt;orderBy('created_at', 'DESC')-&gt;paginate(10, ['page'=&gt;$pageNumber])
    • 哦,别着急,可以直接把分页实例传给collection方法,比如PostResource::collection($paginated_instance)laravel.com/docs/7.x/eloquent-resources#paginationYou may always pass a paginator instance to the collection method of a resource
    • 是的,我这样做了,但它只返回帖子列表。在将帖子包装在 json 数据字段(current_page 等)中时,我缺少 ->paginate(10) 给我的所有其他文件。我也需要将此信息发送到前端,以了解要请求哪个页面。我应该以某种方式将这些字段添加到不同的 API 资源中吗?
    • 不,你不应该分开做,因为它应该给出文档中提到的元和链接字段。 laravel.com/docs/7.x/eloquent-resources#pagination
    • 这就是我正在做的事情:$posts = Post::with('user:id,username', 'user.userInfo')-&gt;orderBy('created_at', 'DESC')-&gt;paginate(10, ['page'=&gt;$pageNumber]);return response()-&gt;json(PostResource::collection($posts), 200)
    猜你喜欢
    • 2022-01-03
    • 1970-01-01
    • 1970-01-01
    • 2021-12-30
    • 2013-11-20
    • 2020-04-04
    • 1970-01-01
    • 2020-08-11
    相关资源
    最近更新 更多