-
Notifications
You must be signed in to change notification settings - Fork 11.1k
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.6] Fix numeric keys in resources #24339
Conversation
This is probably a breaking change to existing applications that are not anticipating the JSON response to contain numerically keyed things and are expected arrays instead of objects. I don't want to "fix" this mid-release for that reason. I'm not really sure returning numerically keyed resource responses is a great idea in the first place. That's odd to interact with in JS. |
I would argue that it's the expected behavior and #23414 was the breaking change. Regardless of the behavior we choose, there shouldn't be an unused method parameter. |
Agreed, this was a breaking change in my application. |
I faced a problem when trying to return and index keyed object using a resource, and analyzing this PR and PR #23414 it seems the fix proposed in this commit makes more sense as it fixes the problem where it happens. I am sorry if I am sounding rude, English is not my native language, I saw that the merged PR (#23414) was submitted by @themsaid who is someone I admire and seems to be very careful and able. As @taylorotwell pointed out, it is very odd to use integer keys on an object in JS, but I faced this issue while porting an project to 5.6. It uses a client-side chart component written in AngularJS to plot a linear chart of monthly accumulated sales. This component expects that each month series to be as follow (shortened for brevity): [{"1":100.0,"2":115.0, ... ,"total":1500.0}, ...] Where each day is represented by a numeric key. I know it is very odd and I would not write it like this, but it was written by a someone else from outside the company. For now I am keeping the old code and not using a resource for the route which returns this data as we cannot rewrite this client-side library. But it took me sometime to find out, it would be nice if we could have both behaviors. |
@taylorotwell I agree with having numeric keys in the response is not a good idea but the resource strips keys of any array nested anywhere, this can easily include custom json fields that use ids as keys. Basically it breaks any custom data formats nested into a response if you use numbers. It should only change the keys for resources imo. Leaving arrays as they are. I got to hack the JSON to have an EDIT: it only needs the first key to be a number and it replaces them all :/ |
@taylorotwell this was a breaking change to our application, we practice the methods outlined here for normalizing our frontend state to allow for easy transaction and lookups with api resources: https://redux.js.org/recipes/structuringreducers/normalizingstateshape The idea is that you can return lookup tables for your resources so that dealing with relational data is much simpler, referencing an entity like This completely breaks that when using API Resources, and looking at the method that causes the issue it appears to be a mixup in implementation. protected function removeMissingValues($data, $numericKeys = false)
{
foreach ($data as $key => $value) {
if (($value instanceof PotentiallyMissing && $value->isMissing()) ||
($value instanceof self &&
$value->resource instanceof PotentiallyMissing &&
$value->isMissing())) {
unset($data[$key]);
}
}
return ! empty($data) && is_numeric(array_keys($data)[0])
? array_values($data) : $data;
}
That aside, the original test for numeric keys that passes in the I understand that using strings for keys seems odd, but it is in fact a very useful and widely adopted approach to architecting frontend applications. Here is an example official example from the vuex repo: https://github.com/vuejs/vuex/blob/master/examples/chat/vuex/store.js Their chat data is normalized, described as threads and messages which can both be referenced by id. This structure would be impossible to get using API Resources from Laravel with this change. You would have to get nested data from the API then post-process it on the frontend. |
I'm still open for this to be fixed if necessary on 5.8. Would require a fresh PR to |
#23414 fixed an issue with
MergeValue
and an associative array. However, this left the$numericKeys
parameter inremoveMissingValues()
unused and thereby broke associative arrays with numeric keys:This PR reverts #23414 and instead fixes the problem in
filter()
:$numericKeys
has to be determined on the data ofMergeValue
, not on the original$data
.Fixes #23595 and fixes #24302.