laravel-query-builder
laravel-query-builder copied to clipboard
AllowedFields are not taking into consideration the relationship fields
Using V4.0.1
When we do the following:
QueryBuilder::for(Post::class)
->allowedFields('author.id', 'author.name')
->allowedIncludes('author');
And query the endpoint like so:
GET /posts?include=author&fields[author]=id,name
It appears to list all the fields of the author
and not just id
and name
.
I think the issue lies here ->get($table)
where it's grabbing the $table
instead of the $relation
from the collection of fields.
I too have just ran into the similar issue (v4.0.1 as well)
I tried applying a resource to each of the keys within the main resource. ie.
public function toArray($request)
{
// return parent::toArray($request);
return [
'id' => $this->id,
'name' => $this->name,
'first_include' => (new FirstResource($this->first)),
'second_include' => (new SecondCollection($this->second)),
];
}
But it appears, when I call the $this->first
it pulls in the entire record, thus does not obey the include'd requirement within the URL.
It would be awesome if any included/related models apply their resource or resource collections.
FYI: I have found a work around.
By checking the relationsToArray
I have found which additional includes have been defined.
Then I just check and convert into either Resource or ResourceCollection as required.
class PrimaryResource extends JsonResource
{
public function toArray($request)
{
$ret_val = [
'id' => $this->id,
'name' => $this->name,
];
// Include resource
if (array_key_exists('first_include', $this->relationsToArray())) {
$ret_val['first_include'] = (new FirstIncludeResource($this->first_include));
}
// Include a resource collection
if (array_key_exists('second_include', $this->relationsToArray())) {
$ret_val['second_include'] = (new SecondIncludeCollection($this->second_include));
}
return $ret_val;
}
}
Wonder if you could do the same with the "field" limits.
I just ran into this issue as well today. Same thing specifying fields on a relationship is not added to the select statement. If the field is for the root object, then it does work.
?include=author&fields[post]=id&fields[author]=id,name
outputs
select post.id from post ...
omitting the ?field[post]=id just results in a select * ...
Same problem here. Using version 4.0.1 too.
You may try to use illuminatech/data-provider instead. It does provide the ability to specify selected fields for the relations.
Hello, I am facing the same issue - is there any solution?
Will upgrading to 5v help?
As pointed out by @PharaohAsh initially the problem is with how the table name is inferred using the relation string:
QueryBuilder::for(Post::class)
->allowedIncludes('author')
->allowedFields('author.id', 'author.name')
// Relation author is transformed to table 'authors'
// AddsFieldsToQuery.php
$table = Str::plural(Str::snake($relation)); // TODO: make this configurable
A workaround could be to specify the included fields with this transformation in mind:
QueryBuilder::for(Post::class)
->allowedIncludes('author')
->allowedFields('authors.id', 'authors.name')
One thing to keep in mind: you always need to include the key for 1-to-1 relations and the foreign_key for 1-to-many relations for Eloquent to be able to correctly associate the retrieved results. Stackoverflow: Query specific columns for relations
@rezaffm Upgrading to v5 will currently not help with this issue.
I'll try to open a PR to fix this issue in a couple of days.
Great stuff, much appreciated.
Would be great if it works for 4v as well then, not ready for Laravel 9 yet :-)
This issue can't be fixed yet?
../Concerns/AddsFieldsToQuery.php
$table = Str::plural(Str::snake($relation)); // TODO: make this configurable
$fields = $this->request->fields()->mapWithKeys(function ($fields, $table) {
return [$table => $fields];
})->get($table);
Why not rollback like the previous version? Is it related to the others?
$fields = $this->request->fields()->mapWithKeys(function ($fields, $relation) {
return [Str::camel($relation) => $fields];
})->get($relation);
Dear contributor,
because this issue seems to be inactive for quite some time now, I've automatically closed it. If you feel this issue deserves some attention from my human colleagues feel free to reopen it.
I could solve this issue using, from the HTTP query, the relationship name in plural and adding the fields that keep the relationships.
For example:
https://myproject.test/query
?limit=5
&include=items,company,subcompany
&fields[orders]=id,created_at,updated_at,company_id,subcompany_id
&fields[items]=id,order_id,qty,price
&fields[companies]=id,name
&fields[subcompanies]=id,name
You can see more details about this scenario here: https://github.com/spatie/laravel-query-builder/issues/605#issuecomment-1370335460
As pointed out by @PharaohAsh initially the problem is with how the table name is inferred using the relation string:
QueryBuilder::for(Post::class) ->allowedIncludes('author') ->allowedFields('author.id', 'author.name') // Relation author is transformed to table 'authors' // AddsFieldsToQuery.php $table = Str::plural(Str::snake($relation)); // TODO: make this configurable
A workaround could be to specify the included fields with this transformation in mind:
QueryBuilder::for(Post::class) ->allowedIncludes('author') ->allowedFields('authors.id', 'authors.name')
One thing to keep in mind: you always need to include the key for 1-to-1 relations and the foreign_key for 1-to-many relations for Eloquent to be able to correctly associate the retrieved results. Stackoverflow: Query specific columns for relations
@rezaffm Upgrading to v5 will currently not help with this issue.
I'll try to open a PR to fix this issue in a couple of days.
Regarding the issue of passing the foreign_key for 1-to-many relations is there is any solution for not passing it?
Spatie, please to update your docs for avoid to lost so much time with this, since this example here will not works with default config: https://spatie.be/docs/laravel-query-builder/v5/features/selecting-fields#content-selecting-fields-for-included-relations
Is missing to mention to use plural when selecting fields for a relation like post->author
Spatie, please to update your docs for avoid to lost so much time with this, since this example here will not works with default config: https://spatie.be/docs/laravel-query-builder/v5/features/selecting-fields#content-selecting-fields-for-included-relations
Is missing to mention to use plural when selecting fields for a relation like post->author
// fields[authors] and NOT fields[author]
// GET /posts?include=author&fields[authors]=id,name
QueryBuilder::for(Post::class)
// authors and NOT author
->allowedFields('authors.id', 'authors.name')
->allowedIncludes('author');