Jump to content

Include RPB Blocks in search results


Recommended Posts

I have not tried this before. So I would like to ask if it is -practically- possible to include RPB blocks in the search results.

As far as I understand - each block is a separate page - so this makes searching a bit tricky. Because how does ProcessWire know where this particular RPB block is located in the frontend - I mean on which page?

If I search for "lorem ipsum" (you get the Idea...) will the search result find the page where a RPB block is placed that contains this string?
 

 

Link to comment
Share on other sites

Hi @Stefanowitsch

What I did is to add a hook at Pages::saved which will save the content of the RPB field to a hidden field which then can be queried via regular selectors.

Each block had a dedicated method createIndex() which was called in a loop:

$blocks = $page->getFormatted(RockPageBuilder::field_blocks);
$index = '';
foreach($blocks as $block) $index .= $block->createIndex();
$page->setAndSave('your_search_index_field', $index);

The benefit here is that you can define custom markup for each block, for example a headline block could just return this for a search index:

public function createIndex() {
  return "** {$this->title} **\n";
}

Does that help?

  • Like 2
Link to comment
Share on other sites

  • 3 weeks later...

Here's my solution to this. For anybody who might integrate it in a similar way:

1. Create a custom search index field and add it to the page templates that should be included in the search. The idea is that all RockPageBuilder blocks on a page will write "their content" into this field so that when searching for keywords the corresponding page (that includes a block) will be listed

2. Create a method called "createIndex" in each RockPageBuilder block class that you want to include in the search results. For example a simple Textblock would only return its body field:

public function createIndex() {
	return "{$this->body}\n";
}

3 Make use of the Pages::saved Hook in ready.php to save the content of all RockPageBuilder bocks into the search index field:

$wire->addHookAfter('Pages::saved', function($event) {

    $page = $event->arguments(0);

    $index = '';

    // Iterate over all fields on the page
    foreach($page->fields as $field) {

        // Check if the field is of the type used by RockPageBuilder
        if ($field->type instanceof FieldTypeRockPageBuilder) {

            // Get the formatted content of the field
            $blocks = $page->getFormatted($field->name);

            // Further processing of the blocks if needed
            foreach($blocks as $block) {

                if (method_exists($block, 'createIndex')) {
                    $index .= $block->createIndex();
                }
            }
        }
    }

    //bd($index);

    // Save index to custom search index field
    $page->block_search_cache = $index;
    $page->save(['noHooks' => true]);
});

4. Inside your search template you can search for pages that contain blocks like this:

 $matches = $pages->find('block_search_cache%=' . $q);

 

  • Like 2
  • Thanks 1
Link to comment
Share on other sites

  • 2 weeks later...

@Stefanowitsch many thanks for sharing your solution, really helped me out.

I modified it a little when implementing. Does the same job but may be a little more optimized.

<?php 

$wire->addHookBefore('Pages::saveReady', function($event) {

    // ...rest of code here

    $page->block_search_cache = $index;
    
    // By hooking before the saveReady event it's possible to set the search cache field value without calling an extra page save
    // $page->save(['noHooks' => true]);
});

Worked for me and just thought to share. Thanks again!

  • Like 3
Link to comment
Share on other sites

On 8/25/2024 at 7:14 PM, FireWire said:

@Stefanowitsch many thanks for sharing your solution, really helped me out.

I modified it a little when implementing. Does the same job but may be a little more optimized.

<?php 

$wire->addHookBefore('Pages::saveReady', function($event) {

    // ...rest of code here

    $page->block_search_cache = $index;
    
    // By hooking before the saveReady event it's possible to set the search cache field value without calling an extra page save
    // $page->save(['noHooks' => true]);
});

Worked for me and just thought to share. Thanks again!

Okay, so you commented out the save method and used the saveReady hook instead? I will try this out!

Saving inside the "saveReady" hook brought me some trouble because I got catched in an endless save-loop. Thats why I used the 'noHooks' option here.

Link to comment
Share on other sites

@Stefanowitsch if you hook into Pages::saveReady then you modify the $page object right before the save happens. For example you can just set $page->title = 'foo' there without saving, because PW saves the page object right after you modified it.

If you hook into Pages::saved the save has already happened. In that case you need another $page->save() after you modified anything.

Sometimes it's better (or necessary) to use Pages::saved, sometimes you can just use Pages::saveReady to be a little more efficient.

  • Like 2
Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
 Share

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...