Jump to content
MateThemes

Add Repeater Matrix Fields to Search Selector

Recommended Posts

Hello everyone!

I am trying to add my repeater matrix fields to the search selector, but unfortunately nothing seems to work for me.

I have following search code in my search.php:

<?php namespace ProcessWire;

// look for a GET variable named 'q' and sanitize it
$q = input()->get('q');

// sanitize to text, which removes markup, newlines, too long, etc.
$q = sanitizer()->text($q);

// did $q have anything in it after sanitizing to text?
if($q) {

	// Make the search query appear in the top-right search box.
	// Always entity encode any user input that also gets output
	echo '<input id="search-query" value="' . sanitizer()->entities($q) . '">';

	// Sanitize for placement within a selector string. This is important for any 
	// values that you plan to bundle in a selector string like we are doing here.
	// It quotes them when necessary, and removes characters that might cause issues.
	$q = sanitizer()->selectorValue($q);

	// Search the title and body fields for our query text.
	// Limit the results to 50 pages. The has_parent!=2 excludes irrelevant admin
	// pages from the search, for when an admin user performs a search. 
	$selector = "title|body~=$q, limit=50, has_parent!=2";

	// Find pages that match the selector
	$matches = pages()->find($selector);
	
} else {
	$matches = array();
}

// unset the variable that we no longer need, since it can contain user input
unset($q);

?>
<main pw-replace='main'>
	<?php include('./includes/_pageheadersearch.php'); ?>

	<div id='content-body' class='uk-section uk-section-large uk-section-large'>
		<div class='uk-container uk-container-small'>
			<?php
			// did we find any matches?
			if(count($matches)) {
				// yes we did, render them
				echo ukAlert(sprintf(_n('Found %d page', 'Found %d pages', $matches->count), $matches->count), "default", "check");
				echo ukDescriptionListPages($matches);
			} else {
				// we didn't find any
				echo ukAlert(__('Sorry, no results were found'), "danger", "warning");
			}
			?>
		</div>
	</div>
</main>

I have tried to add my fields to the selector code (repeater_matrix.aboutsblock_repeaters.mytextfield) . But I didn't get any results.

What I am doing wrong?

Thanks for your help!

Share this post


Link to post
Share on other sites

You could check if one of the newer fieldtype selectors work for you:

https://processwire.com/blog/posts/processwire-3.0.91-core-updates/

I just quickly did a test: It seems if you omit the matrix-fieldname, it works, e.g.

If I have a matrix field called matrix, and inside it is a body field with a matrix-name "richtext":

matrix.richtext.body%=keyword // doesn't work

matrix.body%=keyword // works

$res = $pages->find("matrix.body%=fräsen");
if($res->count) {
    echo '<ul>';
    foreach($res as $match) {
        echo "<li><a href='{$match->url}'>{$match->title}</a></li>";
    }
echo '</ul>';
} else {
    echo "<p>No results found.</p>";
}

 

matrix-gotcha.PNG

  • Like 1

Share this post


Link to post
Share on other sites

Thank you for your answer.

It seems like the problem is, that the field is in a repeater matrix and then in a repeater.

The hierarchy is:

- repeater_matrix
  -- aboutusblock_repeater
  ---- textfield

Could that be?

Share this post


Link to post
Share on other sites

I'm going to jump on this train as well. I've got a matrix with repeater inside and then a body field, just like MateThemes example above.

This works

title|headline|lead|body%=$q

Also this works

matrix.repeater_field.body%=$q

But if I combine both like so, it wont return anything

$selector .= ", title|headline|lead|body%=$q";
$selector .= ", matrix.repeater_field.body%=$q;

If I try to enclose each line in parenthesis it returns every single page on the website, even if the search word is something that doesn't exist on the site

$selector .= ", (title|headline|lead|body%=$q)";
$selector .= ", (matrix.repeaters.body%=$q)";

So I'm kinda almost there, but not quite.

Share this post


Link to post
Share on other sites

I guess this should do it:

$selector .= "title|headline|lead|body|matrix.repeater_field.body%=$q";

 

  • Like 1

Share this post


Link to post
Share on other sites

Unfortunately that doesn't work. "Multidot" selectors can't be used with the | symbol.
 

Share this post


Link to post
Share on other sites
Posted (edited)

Hmm yes, I just tried it out myself and saw this msg: Exception: Multi-dot 'a.b.c' type selectors may not be used with OR '|' fields on line: 896 in /wire/core/PageFinder.php 😞

Guess you'd have to do two separate queries then, one for regular fields, and one for Matrix fields (?). I guess you could file an issue @ Github, if it isn't mentioned already.

edit: Just found this related thread: 

 

Edited by dragan
added link

Share this post


Link to post
Share on other sites
On 4/25/2019 at 9:14 PM, Hurme said:

If I try to enclose each line in parenthesis it returns every single page on the website, even if the search word is something that doesn't exist on the site

Maybe you made a typo somewhere in your selector - the OR-group syntax is working for me:

2019-04-29_232222.png.022de0e098bd5488d3cece209e98b84e.png

 

Share this post


Link to post
Share on other sites

@Robin S What happens if you have multiple pages, where some of the pages have the matrix and some don't? Does it still work for you?

Share this post


Link to post
Share on other sites
9 hours ago, Hurme said:

What happens if you have multiple pages, where some of the pages have the matrix and some don't? Does it still work for you?

There are multiple pages existing in the example above, so yes it does work.

I saw your post in the other thread - the problem is that you are using a single unnamed OR-group for all your selectors. Only one parenthesised selector in the OR-group has to match. So when you do...

$selector = "(template=home|basic-page|product-category, status!=hidden), (template=news-item|product-page)";

...this means that any unhidden page with the home, basic-page or product-category template and any page with the news-item or product-page template will match regardless of any other selectors you later add to the same OR-group. Have another look at the documentation for OR-groups and try giving names to the different OR-groups for template and field values.

  • Like 1

Share this post


Link to post
Share on other sites

Cheers @Robin S, this makes sense to me. I did read about the named groups while trying to solve this, but the explanation felt a little short for me. What does naming the groups actually achieve? 

Share this post


Link to post
Share on other sites
2 hours ago, Hurme said:

What does naming the groups actually achieve?

It tells PW that there is more than one OR-group in the selector string. It's all about specifying what has to match in order for the whole selector string to match - remember that for every OR-group only one selector in the group has to match.

So previously you were doing this...

// Templates
$selector = "(template=home|basic-page|product-category, status!=hidden), (template=news-item|product-page)";
// Fields
$selector .= ", (title|headline|lead|body%=$q), (content_matrix.columns.body%=$q, content_matrix.columns.count>0)";

...which we can represent as this...

// Templates
$selector = "(template selector 1), (template selector 2)";
// Fields
$selector .= ", (field selector 1), (field selector 2)";

...and it is the same thing as...

// Templates
$selector = "foo=(template selector 1), foo=(template selector 2)";
// Fields
$selector .= ", foo=(field selector 1), foo=(field selector 2)";

...which is saying "find any pages that match template selector 1 OR template selector 2 OR field selector 1 OR field selector 2". So this will match a lot of pages that you don't actually want to match.

Whereas this...

// Templates
$selector = "foo=(template selector 1), foo=(template selector 2)";
// Fields
$selector .= ", bar=(field selector 1), bar=(field selector 2)";

...is saying "find any pages that match (template selector 1 OR template selector 2) AND (field selector 1 OR field selector 2)".

  • Like 2

Share this post


Link to post
Share on other sites

Thank you very much for taking the time to explain it. This does makes things much more clear to me. I'll report back once I've had the time to test this.

Share this post


Link to post
Share on other sites

Hello everyone!

So as far as I understand the discussion, it is not possible to make a repeaterfield searchable in a repeater matrix. Is this right?

Thank you!

Share this post


Link to post
Share on other sites

@Robin S It works fine now, thanks for your help. Ryan basically gave the same advice in another thread so it should be doubly fixed now. 😉
 
@MateThemes It works just fine.

You'll want to write it like this:

$pages->find("matrix_field.repeater_field.regular_field%=$searchquery, matrix_field.repeater_field.count>0");

Note that you'll want to leave out matrix type. The count part at the end is to make sure it only returns pages that actually have content in them (seems to be a bug and I haven't checked if it's been fixed yet or not).

Share this post


Link to post
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.


  • Recently Browsing   0 members

    No registered users viewing this page.

  • Similar Content

    • By DooM
      Hello,
      I'm working on something like "structure generator" for my own needs which is run after clean installation of PW to create basic structure, fields, install modules, remove unnecessities, etc.
      I'm trying to remove site/templates/scripts and site/templates/styles folders, but I'm out of ideas already. When I try PHP's unlink function, it says that the path doesn't exists, which is obvious, because it will try to delete those folders under FileCompiler folder. This is probably because PW compilation process? I'm initializing this mine "structure generator" in ready.php.
      Do any of you guys have any idea how to get rid of those folders? My styles and scripts folders are separated, so I don't need those two inside templates folder.
      Thanks for every advice. 🙂
    • By dandeckr
      Hello!
      I'm making my way through my first encounter with ProcessWire, and I'm very near the end of my tasks! I've searched Google, these forums, and for add-ons, but I haven't found any documentation or reference work for implementing boolean searching in the native CMS? Am I missing a thread, add-on, or docs that can point the way? I'm sure I'm not the first to have a need like this? Thanks in advance! 
    • By Violet
      I've been trying to figure this out... It seems like I'm probably missing something really simple, but I'm still puzzled as to how to move forward with this. I'd appreciate any help or suggestions anyone can give.
      Aim: I'm trying to modify the default search template so that my search results come out sorted firstly with those which contain the search term in the title and secondly with those that contain it in the body.
      The basic code where I made sure everything was working first was:
       
      $selector = "title|body~=$q, template=BN-article|BN-infopage, sort=-published, limit=15"; // Find pages that match the selector $matches = $pages->find($selector); // did we find any matches? if($matches->count) { // yes we did $entries = $matches; include("./INC-main-blogroll-panels.html"); } It gave me the search results sorted by publication date, as I expected.
      Next I modified the first portion of the code by using the following to generate the matches as follows:
      $matchest = $pages->find("title~=$q, template=BN-article|BN-infopage"); $matchesb = $pages->find("body~=$q, template=BN-article|BN-infopage"); $entries = $matchest->and($matchesb); However, the problem is that $entries in my resultant displayed list did NOT start with those matches that were in the title first from $matchest. It seemed like $matchest->and($matchesb) sorted the resultant list its own way. This is even without the added complication of trying to use unique() afterward to remove duplicates - which appears to have its own default sort.
      Would anyone please point me in the right direction for what what I'm seeking to do? Thank you so much!
    • By BFD Calendar
      I'm getting an error from sending a search in the search box:
      "Notice: Trying to get property of non-object in /home/mekanoinsa/www/site/assets/cache/FileCompiler/site/templates/_func.php on line 45

      Fatal error: Uncaught Error: Call to a member function each() on null in /home/mekanoinsa/www/site/assets/cache/FileCompiler/site/templates/_func.php:49 Stack trace: #0 /home/mekanoinsa/www/site/assets/cache/FileCompiler/site/templates/search.php(42): renderNav(Object(ProcessWire\PageArray)) #1 /home/mekanoinsa/www/wire/core/TemplateFile.php(287): require('/home/mekanoins...') #2 /home/mekanoinsa/www/wire/core/Wire.php(380): ProcessWire\TemplateFile->___render() #3 /home/mekanoinsa/www/wire/core/WireHooks.php(723): ProcessWire\Wire->_callMethod('___render', Array) #4 /home/mekanoinsa/www/wire/core/Wire.php(442): ProcessWire\WireHooks->runHooks(Object(ProcessWire\TemplateFile), 'render', Array) #5 /home/mekanoinsa/www/wire/modules/PageRender.module(514): ProcessWire\Wire->__call('render', Array) #6 /home/mekanoinsa/www/wire/core/Wire.php(383): ProcessWire\PageRender->___renderPage(Object(ProcessWire\HookEvent)) #7 /home/mekanoinsa/www/wire/core/WireHooks.php(723): ProcessWire\Wire->_callMethod('___renderPage', Array) #8 /h in /home/mekanoinsa/www/site/assets/cache/FileCompiler/site/templates/_func.php on line 49
      This is the code part in _func.php
      // markup for the text $programme = "{$item->stu_programme->title}"; $out .= "<div class='list'><div class='listtext'><span class='verdana_18_bold'><a href='$item->url'>$item->title</a></span><br><br><span class='verdana'><b>$programme</b><br>"; $out .= $item->workshops_list->each( "<font color='green'>| {title}</font>" ); // if the item has summary text, include that too if($item->summary) $out .= "<br><br>$item->summary"; // end markup for the text $out .= "</div>"; Weird, it doesn't happen all the time and I can't figure out what makes the difference....
    • By Robin S
      This module corrects a few things that I find awkward about the "Add New Template" workflow in the PW admin. I opened a wishlist topic a while back because it would good to resolve some of these things in the core, but this module is a stopgap for now.
      Originally I was going to share these as a few standalone hooks, but decided to bundle them together in a configurable module instead.
      Add Template Enhancements
      A module for ProcessWire CMS/CMF. Adds some efficiency enhancements when adding or cloning templates via admin.

      Features
      Derive label from name when new template added: if you like to give each of your templates a label then this feature can save some time. The label can be added automatically when templates are added in admin, in admin/API, or not at all. There are options for underscore/hyphen replacement and capitalisation of the label. Edit template after add: when adding only a single template, the template is automatically opened for editing after it is added. Copy field contexts when cloning: this copies the field contexts (a.k.a. overrides such as column width, label and description) from the source template to the new template when using the "Duplicate/clone this template?" feature on the Advanced tab. Copy field contexts when duplicating fields: this copies the field contexts if you select the "Duplicate fields used by another template" option when adding a new template. Usage
      Install the Add Template Enhancements module.
      Configure the module settings according to what suits you.
       
      https://github.com/Toutouwai/AddTemplateEnhancements
      https://modules.processwire.com/modules/add-template-enhancements/
×
×
  • Create New...