Say I have a simple query to get all rows from a table:
App::make('My_Model')->get();
But, I have a huge number of rows - say 100,000, so many that PHP runs out of memory trying to read them all in.
For some reason I want to go through each of these rows, and do some operation based on them.
Is there any way to tell laravel to give me one row at a time, the way the old mysql_fetch_row worked?
Note: I'm currently solving this by using limit() commands to get 5000 rows at once, which works fine, except that it repeats the query 20 times.
I want to know if there is any built in method in laravel or eloquent to give me the next row, instead of all rows ?
Eloquent ORM is best suited working with fewer data in a particular table. On the other side, query builder takes less time to handle numerous data whether in one or more tables faster than Eloquent ORM. In my case, I use ELoquent ORM in an application with tables that will hold less than 17500 entries.
This allows you to add conditions throughout your code until you actually want to fetch them, and then you would call the get() function.
Laravel Pluck() is a Laravel Collections method used to extract certain values from the collection. You might often would want to extract certain data from the collection i.e Eloquent collection.
For anybody landing here using Laravel 5.2+ (like I did) There is now a 'cursor' method available which returns a Generator
https://laravel.com/api/5.2/Illuminate/Database/Query/Builder.html#method_cursor
So instead of ->get() use ->cursor()
If you want to process them, a thousand at a time say, the chunk()
method in Eloquent
should work for you:
My_Model::chunk(1000, function($my_models)
{
foreach ($my_models as $my_model)
{
// do something
}
});
More in the Eloquent docs
Depends on what you are doing to your data...
The problem is, what is the next row in an application that lives shortly? Unless you are building a command line application that has a cursor, you application lives just for a request. Laravel can give you ways to get a subset of your cursor, so if you need 5000 lines, you can get those 5000 lines at the same time.
So you can use paginate:
$someUsers = User::where('votes', '>', 100)->paginate(5000);
Take and skip:
$page = 5;
$pageSize = 5000;
$users = User::skip($page * $pageSize)->take($pageSize)->get();
Chunk, internally uses paginagion, but it's a little bit restricting, because it will force you to process your whole cursor:
User::chunk(5000, function($users)
{
/// every time this clojure is ran you get a new subset of 5000 rows.
foreach ($users as $user)
{
// do whatever you need with them
}
});
Sidenote: you can save memory by turning query log off:
DB::disableQueryLog();
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With