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] Fix isset if not array or ArrayAccess #29860

Closed
wants to merge 1 commit into from
Closed

Conversation

GrahamCampbell
Copy link
Member

No description provided.

GrahamCampbell referenced this pull request Sep 4, 2019
@taylorotwell
Copy link
Member

This feels hard to read. What are you trying to check?

@taylorotwell
Copy link
Member

Why did we stop using array_key_exists in the first place? Was it a PHP 7.4 reason?

@jasonvarga
Copy link
Contributor

I haven't wrapped my head around the change yet, but I can confirm that upgrading from 5.8.34 to 5.8.35 broke because of this change (which this PR fixes, at least for me)

@taylorotwell
Copy link
Member

taylorotwell commented Sep 4, 2019

In what situation is $offset an array?

I feel like we need to better understand this issue and not just throw code against the wall hoping that is sticks.

@jasonvarga
Copy link
Contributor

Its $this->resource that's the issue.

See this comment

Cannot use object of type Results\ListingResult as array

If your resource doesn't implement ArrayAccess, you now get an error.
When it was using array_key_exists, it would just return false and continue without an issue.

@taylorotwell
Copy link
Member

How does yours not implement ArrayAccess? Are you extending the built-in Laravel resource stuff?

@jasonvarga
Copy link
Contributor

return Illuminate\Http\Resources\Json\Resource::collection($items);

where $items is a collection of Arrayable (but not ArrayAccess) objects.

To be fair, the items are not Eloquent models, but it worked just fine.

@taylorotwell
Copy link
Member

Can someone post an entire stack trace so we can see where this is even being called from and get a better idea of the overall use case?

@matthewnessworthy
Copy link
Contributor

There are a couple of cases where the Resource is instantiated with a non array, non ArrayAccess object

@taylorotwell
Copy link
Member

@matthewnessworthy Like? Where? When? How? We need more details.

@driesvints
Copy link
Member

driesvints commented Sep 4, 2019

Where does the offsetExists call happen?

@jasonvarga
Copy link
Contributor

I misspoke - $items in my comment above is a LengthAwarePaginator.

The stack trace looks like:

[2019-09-04 20:51:57] local.ERROR: Cannot use object of type Statamic\Data\Entries\Entry as array {"userId":"jason","exception":"[object] (Symfony\\Component\\Debug\\Exception\\FatalThrowableError(code: 0): Cannot use object of type Statamic\\Data\\Entries\\Entry as array at /Users/jason/Code/statamic/three/laravel/vendor/laravel/framework/src/Illuminate/Http/Resources/DelegatesToResource.php:53)
[stacktrace]
#0 /Users/jason/Code/statamic/three/laravel/vendor/laravel/framework/src/Illuminate/Support/Arr.php(148): Illuminate\\Http\\Resources\\Json\\JsonResource->offsetExists('resource')
#1 /Users/jason/Code/statamic/three/laravel/vendor/laravel/framework/src/Illuminate/Support/helpers.php(524): Illuminate\\Support\\Arr::exists(Object(Illuminate\\Http\\Resources\\Json\\Resource), 'resource')
#2 /Users/jason/Code/statamic/three/laravel/vendor/laravel/framework/src/Illuminate/Support/Arr.php(387): data_get(Object(Illuminate\\Http\\Resources\\Json\\Resource), Array)
#3 /Users/jason/Code/statamic/three/laravel/vendor/laravel/framework/src/Illuminate/Support/Collection.php(1107): Illuminate\\Support\\Arr::pluck(Array, Array, NULL)
#4 /Users/jason/Code/statamic/three/laravel/vendor/laravel/framework/src/Illuminate/Support/Traits/ForwardsCalls.php(23): Illuminate\\Support\\Collection->pluck('resource')
#5 /Users/jason/Code/statamic/three/laravel/vendor/laravel/framework/src/Illuminate/Pagination/AbstractPaginator.php(647): Illuminate\\Pagination\\AbstractPaginator->forwardCallTo(Object(Statamic\\Data\\Entries\\EntryCollection), 'pluck', Array)
#6 /users/jason/code/statamic/three/cms/app/Extensions/Pagination/LengthAwarePaginator.php(34): Illuminate\\Pagination\\AbstractPaginator->__call('pluck', Array)
#7 /Users/jason/Code/statamic/three/laravel/vendor/laravel/framework/src/Illuminate/Http/Resources/Json/PaginatedResourceResponse.php(28): Statamic\\Extensions\\Pagination\\LengthAwarePaginator->__call('pluck', Array)
#8 /Users/jason/Code/statamic/three/laravel/vendor/laravel/framework/src/Illuminate/Support/helpers.php(1124): Illuminate\\Http\\Resources\\Json\\PaginatedResourceResponse->Illuminate\\Http\\Resources\\Json\\{closure}(Object(Illuminate\\Http\\JsonResponse))
#9 /Users/jason/Code/statamic/three/laravel/vendor/laravel/framework/src/Illuminate/Http/Resources/Json/PaginatedResourceResponse.php(31): tap(Object(Illuminate\\Http\\JsonResponse), Object(Closure))
#10 /Users/jason/Code/statamic/three/laravel/vendor/laravel/framework/src/Illuminate/Http/Resources/Json/ResourceCollection.php(71): Illuminate\\Http\\Resources\\Json\\PaginatedResourceResponse->toResponse(Object(Illuminate\\Http\\Request))
#11 /Users/jason/Code/statamic/three/laravel/vendor/laravel/framework/src/Illuminate/Routing/Router.php(733): Illuminate\\Http\\Resources\\Json\\ResourceCollection->toResponse(Object(Illuminate\\Http\\Request))

@taylorotwell
Copy link
Member

It's a LengthAwarePaginator of plain PHP objects? No Eloquent stuff, etc?

@jasonvarga
Copy link
Contributor

That's right, they are not Eloquent models.

@taylorotwell
Copy link
Member

taylorotwell commented Sep 4, 2019

Hmm, OK. We may have to add this to the upgrade guide that all underlying objects of resources should implement ArrayAccess. I think patching around that may hide other problems.

@driesvints
Copy link
Member

@jasonlbeggs can you post the code of that object?

@GrahamCampbell
Copy link
Member Author

For Laravel 5.8, at least, we shouldn't break code.

@jasonlbeggs
Copy link
Contributor

@driesvints, I think you meant to tag @jasonvarga?

@jasonvarga
Copy link
Contributor

I spoke to Dries outside of this thread, and landed on if you're not putting actual Resource objects in there, it was basically being misused. If it was working, it was a coincidence.

Might apply to @matthewnessworthy 's issue too.

@driesvints
Copy link
Member

@jasonlbeggs yes, sorry!

@jasonvarga yeah exactly. All resource objects should extend the JsonResource class (as it's shown in the docs). If you do that then you'll never run into this issue.

@GrahamCampbell @taylorotwell I think in this case this PR can be closed.

@GrahamCampbell
Copy link
Member Author

GrahamCampbell commented Sep 9, 2019

The phpdoc should be changed from mixed to JsonResource then.

@driesvints
Copy link
Member

@GrahamCampbell no. It's the property that needs to be an instance of JsonResource. Not $offset.

@GrahamCampbell
Copy link
Member Author

Yeh, exactly. That property has type documented as mixed. It should be JsonResource.

@driesvints
Copy link
Member

@GrahamCampbell ah yeah. Feel free to send in a PR 👍

@GrahamCampbell
Copy link
Member Author

Hmmm, why would someone construct a JsonResource with a JsonResource?

@driesvints
Copy link
Member

@GrahamCampbell resources' collections work a little weird and are needed for this I think

@GrahamCampbell
Copy link
Member Author

Heh. Maybe a note in the docs is sufficient.

@lbavendanos
Copy link

I believe that the result obtained when using Query Builder should be a class that implements ArrayAccess and not a stdClass, since not everyone uses Paginator from a Model Eloquent. It is for this reason that it also throws an error when using Resources.

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.

7 participants