1

I have 40k entries in a database, and I am trying to call them using a simple fetch in laravel.

$domains = Domain::where("available", 1)->limit(1000)->get();
return view('domains')
    ->with("domains", $domains);

This works fine up to a few thousand rows. But if I set no limit on the call, I receive a 500 error. I can't fathom why, and I can't work out where I would look to discover how to avoid this issue, I can't seem to find anything in the apache logs, or laravel's own logs located in storage.

David G
  • 6,803
  • 4
  • 28
  • 51
  • 1
    If Apache serves HTTP 500, then there must be something in the error logs if you have error reporting enabled http://stackoverflow.com/questions/845021/how-to-get-useful-error-messages-in-php – Jeff Puckett Jun 17 '16 at 21:53
  • You run out of memory that's allowed for a php script. – N.B. Jun 17 '16 at 21:54
  • 4
    I'm willing to bet you're exhausting the PHP allocated memory pool. You'll have to paginate the results – Machavity Jun 17 '16 at 21:55
  • You were right about the allocated memory. Clearly my setup was flawed somewhere or I've not understood where CentOS stores its logs as this didn't come up. I will implement the chunk solution to avoid having to increase the memory pool too much – David G Jun 17 '16 at 23:13

1 Answers1

7

You can avoid this issue by leveraging the ->chunk command.

Domain::where('available', 1)->chunk(200, function($domain){
    //do whatever you would normally be doing with the rows you receive
    // $domain stuff
});

The purpose of the chunk command is to free up memory after every X iterations of the Model. In this case, I've shown 200.

Sidenote - As the chunk method uses a Closure as the 2nd argument, ensure you use($your_varaibles);

Ohgodwhy
  • 49,779
  • 11
  • 80
  • 110
  • Thanks, didn't know that existed. The thing is I wanted to then use the $domains variable in a return view->with("domains", $domains); I'm not sure how to do that within the scope of the solution here, as I imagine simply moving return view into the chunk's scope would provide me with in this case 200 entries only. So I need to somehow pass them iteratively outside the scope? Small edit to explain – David G Jun 17 '16 at 23:11
  • 1
    @DavidG Sorry for the delayed response - You can just push them into a collection that way you can loop and use them as usual in your views: Alias a collection ahead of time, like this: `$domains = collect([]);`, then inside of your loops, push them onto it, `$domains->push($domain);`. Then you can return `$domains` and use them in your view as per usual. – Ohgodwhy Jun 18 '16 at 01:37