Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[5.8] Check for preserveKeys when serializing a collection from a resource #27985

Merged
merged 2 commits into from
Mar 29, 2019
Merged

[5.8] Check for preserveKeys when serializing a collection from a resource #27985

merged 2 commits into from
Mar 29, 2019

Conversation

rodrigopedra
Copy link
Contributor

As commented by @staudenmeir, when setting the preserveKeys in a resource, but generating a collection from it, the keys are not preserved.

Before this PR the example in the docs should not work:

use App\User;
use App\Http\Resources\User as UserResource;

Route::get('/user', function () {
    return UserResource::collection(User::all()->keyBy->id);
});

As the JsonResource::collection returns a AnonymousResourceCollection and this class does not have a preserveKeys attribute, it fails on keeping the keys when serializing as currently we only check the $preserveKeys property in the object being serialized.

This PR adds a method to the ConditionallyLoadsAttributes trait to handle both the cases of serializing a Resoruce or a Collection of resources.

I used reflection to accomplish this, maybe to 5.9 we could change to using an Interface, I think it would clearer.

Worth noticing that @staudenmeir found this bug while working on issue #27950

@rodrigopedra
Copy link
Contributor Author

Ping @staudenmeir . Please take a look if you have the time

@rodrigopedra rodrigopedra changed the title [5.8] Check for preserveKeys when generating a collection from a resource [5.8] Check for preserveKeys when serializing a collection from a resource Mar 23, 2019
@staudenmeir
Copy link
Contributor

An issue I see:

class UserResource extends JsonResource
{
    public $preserveKeys = true;
}

class UserCollection extends ResourceCollection
{
    public $collects = 'App\Http\Resources\UserResource';
}

return new UserCollection(User::all()->filter->active);

Here, the keys are preserved when they shouldn't be.

Wouldn't your other suggestion solve this?

Add dynamically the $preserveKeys to the AnonymousResourceCollection in instantiation if the collected resource has it.

@staudenmeir
Copy link
Contributor

What if we move this to JsonResource::collection() and add $preserveKeys = false to AnonymousResourceCollection::__construct()? This wouldn't be a breaking change and we could avoid using reflection.

@rodrigopedra
Copy link
Contributor Author

@staudenmeir , thanks for the suggestion, it is much nicer, can you please review it?

Copy link
Contributor

@staudenmeir staudenmeir left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks great!

@taylorotwell taylorotwell merged commit 16f68bb into laravel:5.8 Mar 29, 2019
@rodrigopedra
Copy link
Contributor Author

Thanks! @taylorotwell

While fixing it I felt that this should have been implemented using an Interface, as we do with the ShouldQueue jobs, etc. As we expect the preserveKeys property to be true if this feature is needed.

If you think this is a good approach, I can send a PR to the 5.9 branch

@TBlindaruk
Copy link
Contributor

@rodrigopedra ,
I`m not sure that @taylorotwell is reading comments after PR is merged or closed.

@rodrigopedra rodrigopedra deleted the resources-keys branch March 31, 2019 02:43
@rodrigopedra
Copy link
Contributor Author

@TBlindaruk ok thanks, when I have the time I will try to send a PR so we can discuss there.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants