spatie / laravel-query-builder

Easily build Eloquent queries from API requests
https://spatie.be/docs/laravel-query-builder
MIT License
4.02k stars 395 forks source link

Include Relation is Null #792

Closed beonami closed 2 years ago

beonami commented 2 years ago

I am confused by the results that do not match what is documented. I'am using the package version 5.0.2.

Package Version
{
    "name": "spatie/laravel-query-builder",
    "version": "5.0.2",
    ...
}
App\Models\Post.php
...

protected $fillable = [
    'user_id', 'title', 'body',
];

public function author()
{
    return $this->belongsTo('App\Models\User', 'user_id');
}
App\Http\Resources\PostResource.php
...

class PostResource extends JsonResource
{
    public function toArray($request)
    {
        return parent::toArray($request);
    }
}
App\Http\Controllers\Api\PostController.php
...

class PostController extends Controller
{
    public function index()
    {
        $posts = QueryBuilder::for(Post::class)
            ->allowedFields([
                'id', 'title', 'body',
                'author.id', 'author.name', 'author.email',
            ])
            ->allowedIncludes(['author'])
            ->jsonPaginate();

        return PostResource::collection($posts);
    }
}

Based on the information above, the response from the API is:

http://laravel.local:8083/api/posts?include=author&fields[posts]=id,body&fields[author]=id,name,email

{
    "data": [
        {
            "id": 1,
            "body": "Lorem ipsum dolor sit ame.",
            "author": null
        }
    ],

    ...

Please help, what's wrong? I redo the documentation but the result is the same. Thank you.

beonami commented 2 years ago

Some time later I tried with a different URL, entering the user_id to fields[posts].

http://laravel.local:8083/api/posts?fields[posts]=id,user_id,body&fields[author]=id,name&include=author
...

Response: {
    "data": [
        {
            "id": 1,
            "user_id": 1,
            "body": "Lorem ipsum dolor sit ame.",
            "author": {
                "id": 1,
                "name": "Fahmi Ramdhani",
                "email": "fahmi@laravel.local",
                "email_verified_at": null,
                "created_at": "2022-07-23T02:41:07.000000Z",
                "updated_at": "2022-07-23T02:41:07.000000Z"
            }
        }
    ],

The select feature does not match the requested parameters, the author field is displayed all.

beonami commented 2 years ago

Apparently, the problem is from the fields[relation?] parameter. Where the query builder package or laravel specify the name / alias plural. So there is a difference in the Controller.

App\Models\Post.php
...

public function author()
{
    return $this->belongsTo('App\Models\User', 'user_id');
}

But in controller and selection, allowedFields must be written in plural. allowedFields[authors], NOT allowedFields[author]

...Controllers\Api\PostController.php

$posts = QueryBuilder::for(Post::class)
    ->allowedFields([
        'id', 'user_id', 'body',
        'authors.id', 'authors.name',
    ])
    ->allowedIncludes(['author'])
    ->jsonPaginate();

return PostResource::collection($posts);
Request: GET http://kinetik.local:8083/api/posts?fields[posts]=id,user_id,body&fields[authors]=id,name&include=author
...

Response: {
    "data": [
        {
            "id": 1,
            "user_id": 1,
            "body": "Lorem ipsum dolor sit ame.",
            "author": {
                "id": 1,
                "name": "Fahmi Ramdhani"
            }
        }
    ],
...