Jump to content

Selectors with OR operators?


Oliver
 Share

Recommended Posts

One more selector challenge to face: Currently I'm trying to show a list of pages which's common template owns a “confirmed” field set to true or false and a “user” page reference field.

I need to select all pages that are confirmed OR owned by the user currently logged in, even if they aren't confirmed. And all this paginated and sorted by creation date. When I'm not totally wrong, there is just “,” as kind of an AND operator, but not OR but for cases like “title|headline=value”. Or did I miss something here?

Link to comment
Share on other sites

The example you mentioned "title|headline=value" is a valid selector in PW. http://processwire.com/api/selectors/

I've not tried this particular combination before, but am thinking you may be looking for something like this: "confirmed|owner=1|$user".

$items = $pages->find("confirmed|owner=1|$user"); 

That's assuming that "confirmed" is a checkbox field, and "owner" is a page reference field that you've defined as the owner user you mentioned. For comparison, here's how you might do it with two find()s, which I find a little easier to read:

$items = $pages->find("confirmed=1")->import($pages->find("owner=$user")); 
Link to comment
Share on other sites

i have a similar problem: i want to get

-all items from a list if they match the ID

TOGETHER WITH

-all items wich are marked as global, regardeless of their ID

$search= $pages->find("offer_global=1|offer_from='22|33|44|55");

wont work...

isnt there something like:

$search= $pages->find("offer_global=1|(offer_from='22|33|44|55"));

?

  • Like 1
Link to comment
Share on other sites

-all items from a list if they match the ID

TOGETHER WITH

-all items wich are marked as global, regardeless of their ID

Kind of a hack, but give this one a try:

$pages->find("offer_global|offer_from=1|22|33|44|55"); 

solution work with pagination? I tried, but it didn't seem to bring the results I expexted.

It should work with pagination. At least, I can see I've got code to account for pagination in PageArray::import(). However, I am not certain I've ever actually had to use it. Let me know what kind of result you are getting?

Link to comment
Share on other sites

I tried this:

$templates = implode('|', $templates->find('name^=post_')->getArray());
$posts = $pages->get('/beitraege/')->children('template='.$templates.', post_confirmed=1');
if($user->id != $config->guestUserID) {
$posts->import($pages->get('/beitraege/')->find('template='.$templates.', user='.$user));
}
$posts_page = $posts->find('sort=-created, limit=20');

But it results in all posts being shown.

Changing the last line to:

$posts_page = $posts->sort('-created')->find('limit=20');

results in the first page's content being shown no matter what page I page to.

A problem with the template pagination setting? It did work, when I've been using a simple selector to get my pages directly from the $pages template var.

Link to comment
Share on other sites

This is a fairly complex pagination scenario. I can see why you want to get it all in 1 find() operation here, and if the option I mentioned works, I would probably use it. But if not, you'll need to adjust your setup to perform pagination and sorting at the $pages->find() level, rather than after. Your $posts->find() is not setting pagination details to the PageArray it returns to you because all those pages are already in memory, and pagination is assumed to be for stuff that is not in memory. Writing in the browser here, but try changing your example to this:

$template = $templates->find("name^=post_");
$parent = $pages->get("/beitraege/");  
$posts = $parent->children("template=$template, post_confirmed=1, sort=-created, limit=10"); 
if(!$user->isGuest()) {
   $posts->import($parent->find("template=$template, user=$user, sort=-created, limit=10")); 
   $posts->sort("-created"); // sorts with the previous results 
}

A caveat is that the items-per-page is going to be somewhere between 10 and 20 rather than always 20, at least if the result set is not large. The other caveat is that it's not going to show more than 10 of the given type in each pagination. These may or may not be issues in your case, but just wanted to mention it. There are ways around it, but it'll take more code.

Note the way I'm using the $template var requires the latest PW (or at least one from the last month). You no longer have to do something like implode('|, ...) in recent versions.

  • Like 1
Link to comment
Share on other sites

Here's another way you could do it, by using an SQL query. Also a good example of why I much prefer using PW selectors. :) Still, this should accomplish the desired result without any major caveats.

$template_ids = str_replace('|', ',', $templates->find("name^=post_"));
$parent = $pages->get("/beitraege/");

$sql = <<< _SQL

SELECT pages.id FROM pages
LEFT JOIN field_post_confirmed ON field_post_confirmed.data=1 
   AND field_post_confirmed.pages_id=pages.id
LEFT JOIN field_user ON field_user.data=$user 
   AND field_user.pages_id=pages.id
WHERE pages.parent_id=$parent 
   AND pages.templates_id IN($template_ids)
   AND (field_post_confirmed.data=1 OR field_user.data=$user)
ORDER BY pages.created DESC

_SQL;

$result = $db->query($sql);
$ids = array();
while(list($id) = $result->fetch_row()) $ids[] = $id; 
$items = $pages->find("id=" . implode('|', $ids) . ", sort=-created, limit=20");  
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

×
×
  • Create New...