在 Laravel API 资源响应中包含关系

Including relationships in Laravel API resource response

我的目标是创建一个具有评级关系的书店 API 端点。 Book & Rating 的关系是这样的:

图书模型

/**
* a book has many ratings
*/
public function ratings()
{
    return $this->hasMany(Rating::class, 'book_id')->orderBy('created_at', 'ASC');
}

评分模型

/**
* a rating belongs to a book
*/
public function book()
{
    return $this->belongsTo(Book::class);
}

我的 BookResource 看起来像这样

<?php

namespace App\Http\Resources;

use Illuminate\Http\Resources\Json\JsonResource;

use App\Http\Resources\RatingResource;

class BookResource extends JsonResource
{
    /**
     * Transform the resource into an array.
     *
     * @param  \Illuminate\Http\Request  $request
     * @return array
     */
    public function toArray($request)
    {
        // return parent::toArray($request);
        return [
            'id'        => $this->id,
            'title'     => $this->title,
            'author'    => $this->author,
            'rating'    => RatingResource::collection($this->whenLoaded('ratings'))
        ];
    }
}

我的 RatingResource 如下所示:

<?php

namespace App\Http\Resources;

use Illuminate\Http\Resources\Json\JsonResource;

class RatingResource extends JsonResource
{
    /**
     * Transform the resource into an array.
     *
     * @param  \Illuminate\Http\Request  $request
     * @return array
     */
    public function toArray($request)
    {
        return parent::toArray($request);
    }
}

我想获取所有书籍以及单独的评分,并使用 api.php 文件中的以下两条路径获取单本书及其评分:

Route::get('/books', function() {
    return BookResource::collection(Book::all());
});

Route::get('books/{book}', function(Book $book) {
    return new BookResource($book);
});

当我向邮递员 http://12.0.0.1:8000/api/books 发出获取请求时,我获取了所有书籍,但未加载评级。当我向 http://12.0.0.1:8000/api/books/1 发出获取请求时,同样的事情发生了,这本书没有评级就被退回了。

基于v5.7如何加载关系doc

尝试使用

class BookResource extends JsonResource
{
    public function toArray($request)
    {
        return [
            ...
            'rating'    => RatingResource::collection($this->ratings)
        ];
    }
}

或者如果您想使用 whenLoaded

return BookResource::collection(Book::with('ratings')->get());

正如@honarkhah 向我指出的那样,我在获取 booksbook 时省略了加载 ratings,所以我通过在获取时添加 load() 来修复它这样的数据

Route::get('/books', function() {
    return BookResource::collection(Book::all()->load('ratings'));
});

Route::get('books/{book}', function(Book $book) {
    return new BookResource($book->load('ratings'));
});

你应该: Book::with('ratings')->get(); 对于 /books 端点和 $book->load('ratings');/books/{book}

或者,如果您想始终加载关系,请在 Book 模型中定义: protected $with = ['ratings'];

有关详细信息,请查看 Laravel 文档:https://laravel.com/docs/5.7/eloquent-relationships#eager-loading