Be part of JetBrains PHPverse 2026 on June 9 – a free online event bringing PHP devs worldwide together.

Armani's avatar
Level 17

Using Eloquent Chunk

I have a table with a lot of data inside so when I query the table it takes time. I tried to use chunk or lazy functions but don't know how to use them.

$rows = Person::has('visit')->with('unit', 'rank', 'visit', 'city', 'town', 'village')->filter()->oldest('code')->get();

return view('report', compact('rows',));

and I display results inside a blade file like this:

@foreach($rows as $row)
	          <tr >
				 <td>{{ $loop->iteration }}</td>
		          <td>{{ $row->name }}</td>
				  <td>{{ $row->code }}</td>
		          <td>{{ $row->military }}</td>
		          <td>{{ $row->rank->name }}</td>
		          <td>{{ $row->residence }}</td>
		          <td>{{ $row->birth }}</td>
		          <td>{{ $row->mobile }}</td>
	          </tr>
  @endforeach

I tried this:

$rows = Person::has('visit')->with('unit', 'rank', 'visit', 'city', 'town', 'village')->filter()->oldest('code')->chunk(500, function($people){
	    	foreach($people as $person)
	    	{
	    		
	    	}
	    });

but it gives me error:

foreach() argument must be of type array|object, bool given

I don't know what to write inside foreach loop.

0 likes
10 replies
LaryAI's avatar
Level 58

You can use the chunk method to break up the query into smaller chunks and process them one at a time. The chunk method takes two arguments, the first is the number of records to return in each chunk and the second is a callback function that will be called for each chunk. Inside the callback function you can loop through the records and process them as needed.

For example, you can modify your code to something like this:

$rows = Person::has('visit')
    ->with('unit', 'rank', 'visit', 'city', 'town', 'village')
    ->filter()
    ->oldest('code')
    ->chunk(500, function($people) {
        foreach($people as $person) {
            // Process each person here
        }
    });

Then in your view you can loop through the $rows variable to display the results.

Armani's avatar
Level 17

@LaryAI You repeated what I just said. I tried"

$rows = Person::has('visit')
    ->with('unit', 'rank', 'visit', 'city', 'town', 'village')
    ->filter()
    ->oldest('code')
    ->chunk(500, function($people) {
        foreach($people as $person) {
            return $person;
			// or echo $person;
        }
    });

but still not working.

JussiMannisto's avatar

@mhmmdva This is confusing. filter() is not a query builder function, it's a collection function. So your app should already crash when you try to call it in your query builder chain. Are you sure the app is not crashing before this point in some other foreach loop?

What are you expecting the filter() call to do?

Armani's avatar
Level 17

@JussiMannisto Just ignore the filter function, it is something related to my App. be sure it works fine with filter function.

JussiMannisto's avatar

@Armani Well there's something wrong with your query, and it looks ok apart from the filter() call. Can you show what the function does?

Calling chunk() will add a limit and offset to your SQL. Could you show what your SQL looks like before the chunk call, i.e. the output of

Person::has('visit')
    ->with('unit', 'rank', 'visit', 'city', 'town', 'village')
    ->filter()
    ->oldest('code')
    ->toSql()
Armani's avatar
Level 17

@JussiMannisto there's nothing wrong with code, I just wanted to load data more optimized. forget about filter() function:

$rows = Person::has('visit')
    ->with('unit', 'rank', 'visit', 'city', 'town', 'village')
    ->oldest('code')
    ->lazyById(500);

This code worked for me.

JussiMannisto's avatar

@Armani Edit. Nevermind, I took a closer look at your previous code snippet and that's not how chunk() works.

Chunk doesn't return you a result set. It's for doing operations in batches. I think you got the foreach error when you were trying to iterate $rows since chunk() will return a boolean value.

If you wanted to store all people to $rows using chunk(), you'd do it this way instead:

$rows = collect();

Person::has('visit')
	->with('unit', 'rank', 'visit', 'city', 'town', 'village')
	->filter()
	->oldest('code')
	->chunk(500, function($people) use($rows) {
		foreach($people as $person)
			$rows->push($person);	
	});

But your method is fine too.

psrz's avatar

If you're showing some data on your view, then what you want is paginate(), not chunk. When you're using chunk on the query builder that means your getting all the records (matching the criteria), but you get them 500 at a time

https://laravel.com/docs/10.x/pagination#paginating-eloquent-results

Like @jussimannisto just pointed out, the filter() function when chaining query builder methods seems odd. Is that a scope of the Person model ?

Armani's avatar
Level 17

@psrz I know there's pagination but in this situation I need to show all the records at once.

Hassankhan's avatar

You can only optimize This Code Like That

$rows = Person::with(['unit', 'rank', 'visit', 'city', 'town', 'village'])
            ->whereHas('visit')
            ->orderBy('code', 'asc')
            ->paginate(10);

return view('report', compact('rows'));

Please or to participate in this conversation.