Как я могу получить вложенную базу данных отношений с указанием c столбцов с помощью метода Eloquent :: with? - PullRequest
0 голосов
/ 01 августа 2020

У меня есть следующие 3 таблицы:

сообщения <- (hasMany) - <strong>пользователи - (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

Взаимосвязи, указанные ниже:

Пользователь. 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')

, который возвращает что-то вроде этого:

{
    "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_picture и user.userInfo:user.user_info.name,user.user_info.profile_picture

1 Ответ

1 голос
/ 01 августа 2020

Вы можете использовать ресурсы API https://laravel.com/docs/7.x/eloquent-resources#introduction

Ресурс API действует как уровень преобразования, который находится между вашими моделями Eloquent и ответами JSON, которые фактически возвращаются в пользователей вашего приложения.

Вы можете создать ресурс API для сообщения и использовать его везде, где вы возвращаете сообщение в ответе.

Ресурсы 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,
                ]
            ]
        ];
    }
}

А потом куда бы вы ни захотели вернуть пост в качестве ответа.

Контроллер

// $post is a Post Model Instance.

return new PostResource($post); 

Если у вас есть коллекция

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

return PostResource::collection($posts);

PostResource будет применяться для каждого экземпляра модели в вашей коллекции, а затем будет возвращен вам в качестве ответа JSON.

[ ПРИМЕЧАНИЕ ]

Вы можете создать аналогичный ресурс для r пользователей и любой модели. Это упрощает настройку ответа по своему усмотрению.

Также в приведенном выше примере. Вместо того, чтобы иметь 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,
            ]
        ];



...