Lazy loading possible when using Pages::factory?


I’m doing my first Pages out of the database adventure (Inspired by this awesome cookbook).
I noticed that when you use the paging your query in ->children() always get re-executed completely. And I was wondering if there’s a way to optimise this.
One thing I noticed is that the panel, when using paging, always send a get parameter page and I tried to limit my queries so I don’t always query everything but only the active data. Only thing is that when I do that, the paging (obviously) disappears because there aren’t as many records any more.

So my main question is: Is there any way to optimise your data retrieval in the panel when retrieving data from a database.

If there are also some other cool tips&tricks about working with a database as pages, feel free to share :sweat_smile:


use Kirby\Uuid\Uuid;
use Kirby\Cms\Content;

use App\Models\Customer;

class CustomersPage extends Kirby\Cms\Page
    public function children()
		if(!empty($page = get('page')))
			$users = Customer::limit(20)->offset($page*20)->orderBy('firstname', 'desc')->get();
			$users = Customer::orderBy('firstname', 'desc')->get();


        foreach ($users as $user) {
            $customers[] = [
                'slug'     => 'cid-'.$user->id,
                'num'      => null,
                'template' => 'customer',
                'model'    => 'customer',
                'content'  => [
					'cid' => $user->id,
					'uuid' => Uuid::generate(),
					'title' => $user->firstname.' '.$user->lastname,
					'firstname' => $user->firstname,
					'lastname' => $user->lastname,
					'email' => $user->email,
					'company_name' => $user->company_name,
					'delivery_street' => $user->delivery_street,
					'delivery_street_nr' => $user->delivery_street_nr,
					'delivery_zip' => $user->delivery_zip,
					'delivery_city' => $user->delivery_city,
					'vat' => $user->vat,
					'phone' => $user->phone,
					'fleet_discount_perc' => $user->fleet_discount_perc,
					'is_dealer' => $user->is_dealer,
					'gdpr_optin' => $user->gdpr_optin,
					'created_at' => $user->created_at,

        return Pages::factory($customers, $this);

The problem at this moment if you open the Virtual page in the panel every open, but also every “next/previous” page click generates 20 queries. :thinking:

I think the easiest way to work with large collections currently is to avoid the normal panel sections and write your own. Also, “virtual pages” aren’t meant to be lazy loaded, so you probably want to avoid those in general.

There’s a feedback ticket here: Lazy loading virtual pages · Kirby Feedback, but I don’t think it will ever be implemented, goes a bit too much against how Kirby 3 works

you need a cache for your children method. expect it to be called more than once per request. something like the core trait does

but be aware that you might need to flush your cache if you update data in the database.