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

时间:2019-06-04 13:21:40

标签: php laravel laravel-5.7

我的目标是建立具有评级关系的书店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发出get请求时,也会发生同样的事情,这本书没有评分就退回了。

如何基于v5.7 doc

加载关系

3 个答案:

答案 0 :(得分:2)

您应进行以下操作: 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

答案 1 :(得分:1)

尝试使用

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

或者如果您想使用whenLoaded

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

答案 2 :(得分:0)

正如@honarkhah指出的那样,我在获取ratingsbooks时省略了加载book的操作,因此在获取数据时通过添加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'));
});