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.2] Allowed Memory size exhaused when accessing undefined index in toArray #14627

Closed
rchoffardet opened this issue Aug 4, 2016 · 11 comments
Closed

Comments

@rchoffardet
Copy link

rchoffardet commented Aug 4, 2016

Hey !

Succeed to reproduce and isolate a curious bug :
When I try to access an undefined index, it crash and throw "Allowed Memory size exhaused"
Here is the reproduceable bug :

public function toArray() { $buffer = parent::toArray(); dd($buffer['random']); return $buffer; }

Neither of isset() nor empty() worked for me

(PHP 7.0.1 / Debian 8.4)

Regards,
Robin

@TomKita
Copy link

TomKita commented Aug 7, 2016

You are just running out of memory when calling parent::toArray(). You either need to reduce the amount of items in your collection or increase your allowed memory allocation.

@rchoffardet
Copy link
Author

No, it's a bug. I don't know if it's coming out of Laravel or PHP itself, but it's a bug, 100% positive.

This issue showed because I was treating pivot values while serializing a plain object. It should throw me an undefined index error.

To fix this issue, i had to ensure to never try to serialize this plain object, and only serialyze it as a relation.

As an example :
Post::where('user_id', '=', 1)->get()->toArray()
Doesn't work, but following does :
User::with('posts')->where('id', '=', 1)->get()->toArray()

Which is totally normal, but the espected error was undefined index not Allowed memory excedeed

@themsaid
Copy link
Member

themsaid commented Aug 7, 2016

I don't get it, what is this method?

public function toArray() { $buffer = parent::toArray(); dd($buffer['random']); return $buffer; }

@TomKita
Copy link

TomKita commented Aug 7, 2016

@rchoffardet

Your examples are not the same thing.

Post::where('user_id', '=', 1) will return just one row.

While User::with('posts')->where('id', '=', 1)->get()->toArray() will run two queries and return multiple posts. Inflating your memory usage.

Try:

User::with(['posts' => function ($query) {
    $query->take(1);
}])->where('id', '=', 1)->get()->toArray();

This should limit the number of posts you get. If you still get allowed memory exceeded then there might be something in your mutations that is causing too much nesting an thus exceeding your memory limits.

@themsaid I think he is overriding the default behavior of toArray() in his model.

@rchoffardet
Copy link
Author

@themsaid :
Overriding toArray() method allow us to add custom feature before serialization, like cleaning/filter model or add some stuff. I often use it to format dates attributes to ISO 8601.

@TomKita :
Both lines of codes will return the same thing : all post belonging to the user with id equals 1
The difference is :
Post::where('user_id', '=', 1) will return a collection of Post object
User::with('posts')->where('id', '=', 1)` will return a collection of only one user and inside it a collection of posts
Both are almost the samen and memory usage is nearly the same.
(And FYI, I fixed it and use the second query everywhere, it just works fine, with no slow down nor intensive memory usage)

The problem is :
With the first option, pivot table's values aren't return and in my toArray() i try to access one of them. It should be throwing me an error undefined index not allowed memory exceeded.
Let's say that accessing an undefined attribute causes this effect because of my database design or stuff like that. Shouldn't isset() or !empty() (notice ! ) return me false instead of true ?

I do not know if that is a laravel bug or my specific version of php, and i'll try to reproduce it again. But this is clearly a bug.

@rchoffardet
Copy link
Author

Just tested with Post::find(1) and got a Allowed memory exhausted while accessing an undefined attribute. This shouldn't occur.

@TomKita
Copy link

TomKita commented Aug 7, 2016

Sorry, just to clarify you did something like this Post::find(1)->undefined and got allowed memory exhausted?

@rchoffardet
Copy link
Author

No, i did Post::find(1)->toArray() and access an undefined attribute inside the toArray() overrided method

@TomKita
Copy link

TomKita commented Aug 7, 2016

If you remove the overridden method from your Post model and call Post::find(1)->toArray() do you still get the error?

@rchoffardet
Copy link
Author

No

@rchoffardet
Copy link
Author

rchoffardet commented Sep 2, 2016

I finally find my problem: Errors are correctly thrown and written in laravel log, although, as i'm building a private REST api, I was encoding exception in JSON, which may consume too much memory (maybe circular references ?).

Removing trace from the exception resolved my problem.

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

No branches or pull requests

3 participants