ethanbeyer Posted May 22, 2018 Share Posted May 22, 2018 I'm trying to build a Search Template. The way I had been doing it was by constructing a Selector one string at a time in an array, and then imploding that array with ", " in order to create a Selector that was passed to $pages->find($selectorStr). This is a bare-bones example of what I was doing: $search = $sanitizer->selectorValue($input->get('s')); $selector[] = 'template=member'; $selector[] = "field1|field2|field3%={$search}"; $selector[] = "(repeaterField.fieldX|repeaterField.fieldZ%={$search})"; $selectorStr = implode($selector, ", "); $results = $pages->find($selectorStr); This worked as expected, and I was able to utilize OR-groups within the Selector. There is a problem, though: for whatever reason, despite sanitizing the incoming value, if the user input a string like "test,foo", ProcessWire threw this error: Exception: Unknown Selector operator: '' -- was your selector value properly escaped? field='foo', value='', selector: 'include=all, children.count>0, title%=test,foo' (in /var/www/public/wire/core/Selectors.php line 378) So I moved on to Selector Arrays, and now I'm having trouble with OR-groups. I found out about Selector Arrays (not documented at all as far as I can see in the API Reference) through a ProcessWire blog post about 3.0.13. Here's the code (using the actual field names, unlike above): $selectorArray = []; // template $selectorArray[] = ['template', 'directory-member']; // basic fields $selectorArray[] = [ 'field' => [ 'dm_firstName', 'dm_middleName', 'dm_lastName', 'email', 'dm_ficmTitle', 'dm_addressStreet', 'dm_addressCity', 'dm_addressState', 'dm_addressPostalCode', 'dm_birthday', 'dm_phone1', 'dm_phone2' ], 'operator' => '%=', 'value' => $searchStr ]; //repeaters $selectorArray[] = [ 'field' => [ 'dm_contactREP.dm_contactMethod', 'dm_contactREP.dm_contactValue' ], 'operator' => '%=', 'value' => $searchStr, 'group' => 'repeaters' ]; // search the parent's name $selectorArray[] = [ 'group' => 'parentTitle', 'field' => 'parent.title', 'operator' => '%=', 'value' => $searchStr, ]; // sort $selectorArray[] = ['sort', 'dm_lastName']; $selectorArray[] = ['sort', 'dm_firstName']; The problem is that the Selector is rendered like this (clauses broken into Newlines): template=directory-member, dm_firstName|dm_middleName|dm_lastName|email|dm_ficmTitle|dm_addressStreet|dm_addressCity|dm_addressState|dm_addressPostalCode|dm_birthday|dm_phone1|dm_phone2%=test, repeaters@dm_contactREP.dm_contactMethod|dm_contactREP.dm_contactValue%=(test), parentTitle@parent.title%=(test), sort=dm_lastName, sort=dm_firstName, status<1024 For OR-groups, the whole clause should be wrapped in parentheses - not just the value I'm searching for! So, two questions: Why would a comma in the search value break things that are supposed to be sanitized, and two, how do I get the OR-groups to work as intended? Link to comment Share on other sites More sharing options...
Robin S Posted May 23, 2018 Share Posted May 23, 2018 16 hours ago, ethanbeyer said: There is a problem, though: for whatever reason, despite sanitizing the incoming value, if the user input a string like "test,foo", ProcessWire threw this error: Exception: Unknown Selector operator: '' -- was your selector value properly escaped? field='foo', value='', selector: 'include=all, children.count>0, title%=test,foo' (in /var/www/public/wire/core/Selectors.php line 378) Put quote marks around your search string so PW can distinguish between the selector string and the search string, e.g. $selector[] = "(repeaterField.fieldX|repeaterField.fieldZ%='{$search}')"; 16 hours ago, ethanbeyer said: So I moved on to Selector Arrays, and now I'm having trouble with OR-groups. That is a more advanced usage than what is covered in the blog post. You'll need to use the "verbose" version of a selector array. Ryan gives an example of a verbose selector array this in this GitHub comment. And for more details and the specifics of OR-groups in a selector array see the comments in Selectors.php here and here. TBH you might find it easier to stick with selector strings for such things until we have proper documentation for selector arrays. 2 Link to comment Share on other sites More sharing options...
ethanbeyer Posted May 23, 2018 Author Share Posted May 23, 2018 5 hours ago, Robin S said: Put quote marks around your search string so PW can distinguish between the selector string and the search string, e.g. $selector[] = "(repeaterField.fieldX|repeaterField.fieldZ%='{$search}')"; Well, I feel a bit silly. I didn't think that needed to be done because of the call to $sanitizer->selectorValue($input->get('s')); . Anyhow, you solved my problem - and I think you're right: String Selectors are probably an easier method to go with than Array Selectors until they've been documented better. 1 Link to comment Share on other sites More sharing options...
Recommended Posts
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 accountSign in
Already have an account? Sign in here.
Sign In Now