$pages->find() with an array

Hi everyone, I have a array (from a checkboxes field in a blueprint):

$pages_to_fetch = [uri1, uri2, ...];

which I would like to use with

$pages->find($pages_to_fetch)

Can I achieve this?

I have to tried to call “$pages->find()” looping through the array but then I can’t figure out how to merge the results into a regular “$page” object…

You won’t get a $page object, you’ll get a collection.

$collection = call_user_func_array(array($pages, 'find'), $pages_to_fetch);
2 Likes

could you do something like:

$pages_to_fetch = ['uri1', 'uri2', ...]
$fetch_results = array();

foreach ($pages_to_fetch as $page_to_fetch) {
   $fetch_results[] = $pages->find($page_to_fetch);
}

foreach ($fetch_results as $fetched_page) {
   echo $fetched_page->title()
   ...
}


Sure. There are many ways of getting a similar result. I just like to be concise. And my method produces a kirby collection while yours is a regular array. Functionally equivalent to your method would be:

$collection = array_map(function($uid) {
    return site()->find($uid);
}, $pages_to_fetch);

But now I’m just mucking about. I just like doing things using native functions when they’re available.

@walkerbox:
call_user_func_array and array_map are new to me - the more I get better at this stuff the more i know I don’t know ~ I misunderstood your first post.

I’m not sure I understand the difference between a kirby collection and an array - does this just mean that there are methods I can use on a collection, such as $collection->method()?

A collection is of type object on which you can use the collection (or $pages) methods (like find(), filter() etc.) which you can’t use on an array.

Oh, man. You are going to have so much fun! Also check out array_walk() and array_filter() if you’re interested in native methods for handling arrays. Finally, it’s worth knowing that kirby has $pages->filter() and $pages->map() available.

I’ve came across call_user_func_array() but it seems I didn’t understand it… can’t wait to try out your solutions guys !

Works like a charm! Here’s the basic use I’ve made using your solution

// Get a checkbox field content (after basic cleaning) from a page and put it in an array.
$pages_to_fetch = str_replace(' ', '', $pages->find('pagename')->checkboxfield());

// Put the URIs in an array.
$uris = explode( ',', $pages_to_fetch);
    
// Retrieve the collection of pages using the URIs
$collection = call_user_func_array(array($pages, 'find'), $uris);

// Get page data or children data (that's what I wanted).
foreach ($collection as $fetchedpage) {
    echo $post->title();
    // I guess there's way to call this within the call_user_func_array() above?
    foreach ($fetchedpage->children() as $post){
        echo $post->uri()
    }
}
1 Like

Glad I was of some use :smile:

    echo $post->title();

I’m not sure what this is doing. $post hasn’t been defined yet. Instead of multiple foreachs there’s no reason why you can’t just use:

foreach ($collection->children() as $post) {
    echo $post->parent()->title();
    echo $post->uri();
}

A mistake due to overwhelming excitement : )

Hi, this topic is kinda old but I have a similar problem:
I use the great multiselect plugin to select pages from a query.
The pages are saved like checkboxes values (slug1, slug2, slug3).

I tried
$uris = $page->multiselectfield()->split()
which gives me an array of the selected slugs.

Now I tried to use
$collection = call_user_func_array(array($pages, 'find'), $uris);
to make a collection.

But obviously that didn’t work as
foreach($collection->children() as $post)
gives me no results.

I also tried the method from above (by tasinttttttt) but it didn’t give me any results either.

Does anyone have a clue what I am doing wrong?

You should be able to simple pass an array (since Kirby 2.3):

$collection = $pages->find($uris);
1 Like

Thank You, That looks clean. But how can I use the collection in a foreach loop?

Now I have:

$uris = $page->multiselectfield()->split();
$coll = $pages->find($uris);
foreach($coll->children() as $post){
    echo $post->title();
}

It looks like that doesn’t even return ANYTHING in the loop.
I also tried without children() but without luck.

Sorry, I think that was my mistake – I didn’t know that find() just looks for the top level of pages (or am I wrong) and I am looking for subpages.

So it looks like
$pages->children()->find($uris);
did the trick.

Great that you found a solution.

PS: Please use Markdown code blocks when posting multiline code in the future. They use three backticks at the start and end on separate lines. I have changed it for you above.

Thank you, I will do in the future!

Just for information:
I found a solution that looks cleaner and easier to me, now I don’t loop through a collection, but through the array itself and inside the loop I use the ‘uid’ that the array returns to get a page. (I now also use $page->index() instead of $page->children().

$uids = $page->multiselect()->split();
foreach($uids as $post){
    $post = $pages->index()->findBy('uid', $post);
    echo $post->title();
}

If you only need to search within the children of $pages, it makes more sense to use $pages->children() instead of $pages->index() because the last option goes looks in the complete tree, not just the child pages and is therefore less performant.

BTW. code blocks are created with three backticks without a space between them.

Just for completeness, I used this today.

To narrow it down a bit, it looks like this:

$collection = $pages->find(['tags/shoes', 'tags/bananas']);

foreach($collection as $item) {
  echo $item->title();
}

It works fine.