Jump to content
formmailer

Selector and Page reference field

Recommended Posts

Hi,

I need a selector to find pages that are using the template "poi" and that are having a page reference to a page with the title "Zoo".

The page reference field is called poi_type.

How would I do this?

I tried this:

$poi = $pages->find(template=poi, poi_type.title='Zoo'); 

But it doesnt work because there is no field poi_type.title.

/Jasper

Share this post


Link to post
Share on other sites
$pr = $pages->get("title=Zoo");
$poi = $pages->find("template=poi, poi_type=$pr");

  • Like 1

Share this post


Link to post
Share on other sites

Now it becomes more complicated: I need to include page references to the selector, for example: Zoo, Theme park and Museum.

The first line becomes:

$pr = $pages->get("title=Zoo|Theme park|Museum");

But the second line only finds the pages in the first category (or last, I don't remember).

I assume that I need to cycle through $pr and include the results into the existing Array ($poi). Is that correct?

/Jasper

Share this post


Link to post
Share on other sites

Works with many to many too.

$prs = $pages->find("title=Zoo|Theme park|Museum"); // maybe also use the name or id
$poi = $pages->find("template=poi, poi_type=$prs");

EDIT: corrected code. yours doesn't work because "get" will return only 1 page and not page array.

  • Like 6

Share this post


Link to post
Share on other sites

Thanks Soma!

I often forget what returns a single object or an array of objects. I really need to sit down some time and learn this basic stuff for real. It will save me quite some time searching and asking while building new things. :)

Yes, I will probably use the page ID instead of the title, that seems to be a bit safer.

/Jasper

Share this post


Link to post
Share on other sites

Hi, I'm new here, I'll start by posting in an existing thread ;-)

I'm trying to do something similar than the OP, but I can't get it to work :

Basically,

- I have pages with template "one-category", where each page represent one category

- I have pages with template "one-article", which are used for the actual contents.

- one of the fields of "one-article" is "article_categories", it is of type "Page", more specifically "Multiple pages (PageArray)". It is used to reference a list of pages of type "one-category" (which means it is used for assigning categories to each article).

Now, I want to select, for each existing category pages, the list of the "one-article" pages which are referencing the category.

For troubleshooting, I also try to "just" select all the "one-article" pages which are referencing one single category page.

here is the code :

$the_articles = $pages->find("template=one-article"); // select all existing real pages
$the_cat = $pages->get("template=one-category, title='cat1'"); // select one category page
$the_list = $the_articles->find("article_categories=$the_cat"); // select real pages referencing the desired category page

as a result,

- this is working if I have only 1 category referenced in the articles : $the_list->count() returns '1' for the relevant article, and I can use the returned objet

- but it (seems to) fail as soon as I add a second category to this article : $the_list->count() now returns '0', while I would expect it to still return '1'

any idea ?

  • Like 1

Share this post


Link to post
Share on other sites

Welcome to the forums er314. I think what you want may be this:

$the_cat = $pages->get("template=one-category, title=cat1"); 
$the_list = $pages->find("template=one-article, article_categories=$the_cat"); 

It sounds like you might be performing this from your one-category template, so in that case you could just do this:

$the_list = $pages->find("template=one-article, article_categories=$page");

In addition to the above, you might want to specify a "sort" in your selector, like "sort=date" (if you have a field called that) or "sort=title" or something like that. Though if you change your call to something like this, then it would automatically sort by whatever is defined with the /articles/ page:

$the_list = $pages->get("/articles/")->children("article_categories=$page"); 

Share this post


Link to post
Share on other sites

er31,

Where do you call this code, in your categories template?

I'm not sure but i guess the problem lies in the fact that $pages->get returns a Page and not a PageArray. You should alter the $the_cat part is guess, but i could be wrong :)

Share this post


Link to post
Share on other sites

Thanks,

Currently, for testing (and for understanding/learning !) purpose, I'm doing the request outside of the category template,

So yes Ryan your 1st solution, the one with 2 selects, is working, thanks a lot !

For the sake of understanding/learning,

as I will have to perform several requests/selections of this type in the same block of code, my aim was to

- first, perform only once the supposedly "heaviest" request (the one which queries all pages)

- then, perform the subsequent requests not on all pages, but on the "one-article" subset of pages

Hence, my initial code, which added an intermediate step (3 selections instead of 2, with the heaviest first)

-> Ryan, do you know exactly what was wrong in my initial code ?

Can it be fixed, while preserving this 3 steps behaviour ?

Or should I just forget about that, given that this kind of optimization is probably negligible ?

(my aim is to display, in the category tree view, the number of "one-article" pages for earch category ; well, a bit like the "Pages" view in PW admin interface...)

Share this post


Link to post
Share on other sites

You think could use something like this:

$categories = $pages->find("template=one-category");

foreach ($categories as $cat) echo '<p>' . $cat->title . ' (' . $pages->count("template=one-article, article_categories=$cat") . ')</p>';

or, if you use it in your category template:

echo '<p>Category ' . $page->title . ' has ' . $pages->count("template=one-article, article_categories=$page") . ' articles!</p>';

Edit:

Or should I just forget about that, given that this kind of optimization is probably negligible ?

Processwire is optimized for such requests, so there shouldn't be any serious penalties for using several queries in a loop.

Share this post


Link to post
Share on other sites

Interesting, I was not aware of this usage for the count() method.

Ok, this is working too.

Now I have plenty of options for my code, thanks ;-)

Share this post


Link to post
Share on other sites
$the_list = $the_articles->find("article_categories=$the_cat"); // select real pages referencing the desired category page
-> Ryan, do you know exactly what was wrong in my initial code ?

There's nothing wrong with your code, but just a difference of context here. The issue is that a few of the in-memory selectors sometimes aren't as smart as the DB-driven ones. Your code quoted above is an in-memory find() provided by the WireArray class. It is used throughout the system, and it performs literal string comparisons. Whereas the DB-driven one is sending out queries to be answered by MySQL, often with a lot more context than string comparison. Most of the time, the two should perform the same, so this is one instance where they don't. It may be something I can account for. I hadn't noticed this before because it's somewhat rare to do this type of in-memory find() where you are finding/filtering pages based on pages within pages. In-memory finds and filters aren't ideal because it usually means that more pages have been loaded into memory than were actually needed. So it's preferable to avoid situations that result in post-filtering or post-finding, when possible. In your case, it sounds like you are going to use all the pages, but just using find() to group them differently. If you want to stick with that route, I would do this:

$the_list = new PageArray();
foreach($the_articles as $a) {
 if($a->article_categories->has($the_cat)) $the_list->add($a); 
}

The above also reveals the technical reason why the in memory find failed. The string value of $article_categories and $the_cat won't match unless $article_categories only has 1 category and it is $the_cat. That's why we had to use has() to compare them, which is something that WireArray::find has no contextual awareness of. I'm going to see if there is some way to make them work the same. Thanks for bringing it up.

Share this post


Link to post
Share on other sites

This looks like a wordpress forum with all those the_variables ;)

Share this post


Link to post
Share on other sites

Now this is quite a detailed explanation !

thanks again

(@diogo : I've never used wordpress before, this is pure coincidence ;-)

Share this post


Link to post
Share on other sites

Works with many to many too.

$prs = $pages->find("title=Zoo|Theme park|Museum"); // maybe also use the name or id
$poi = $pages->find("template=poi, poi_type=$prs");

EDIT: corrected code. yours doesn't work because "get" will return only 1 page and not page array.

Just wanna thank Soma for this. Been searching for selector for page references for an hour. This solved my problem. :)

  • Like 1

Share this post


Link to post
Share on other sites

Is it possible to use the value of a referenced page in a "show field if" query? Like in the screenshot.

 

The page reference field is block_selector, the refernced page has the template select_value. Thx for any help!

image.png.c68dd6c5e8884ef49396ce3409716f89.png

image.png.bd697dc7e4f79e70fef5312983a7e598.png

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 wesp
      Hello everyone,
      Is there a way to access the key number of an item in a page reference field and then output it as a value?
      So for example I want to automatically output the number 1 if the referenced page is the first in the list and have it be updated when the list is reordered via drag and drop.
      Thanks in advance!
    • By Roberts R
      I have simple page structure:
      category subcategory simple-product simple-product simple-product simple-product subcategory .... category2 so Im at category page and running
      $pages->find("template=simple-product, has_parent=$page, limit=8"); and it returns 0 pages
       
      but this returns 4 pages
      $pages->find("template=simple-product, has_parent=$page"); Can someone explain why limit does not work here?
      EDIT:
      So I did some tests and it seems that any limit=n where n is >= actual page count that is possible ... selector return 0 results.
    • By jds43
      Hello, I have a Page Reference by template radio button field to promote a certain page (only two options), but I'd like to target the page that isn't selected. This would be used dynamically throughout the site.
      Does anyone know how I could accomplish this? Would I use something like remove() or not()?
       
    • By Manuel
      Hi everybody!
      I'm new to PW and just did the beginner-tutorial “Hello Worlds”, a beginning ProcessWire tutorial --> Link
      After extending the template from the original tutorial with a page_reference-Field (Page-Field value type is configured as single page),
      PW throws a fatal error when i try to output multiple pages:
      $planets = $pages->find("template=planet, sort=-title"); foreach($planets as $planet) { echo $planet->title; echo $planet->planet_reference->title; } Should return three Pages, but throws the following error:
      When i try to output the field with a single page, everything just works fine:
      $planet = $pages->get(1018); echo $planet->title; echo $planet->planet_reference->title; I've tried to solve the problem with myself (and google), but i can't fix the error.
      Thanks a lot!

      My enviroment:
      OSX Mojave / MAMP (PHP 7.2), PW v 3.0.123
    • By Hubris
      Hi there!
      I'm using some page reference fields to create lists of tags, categories, years, etc.. I'm able to find the pages like so:
      $pages->find("template=project, {$filter}={$page->title}"); Which dynamically does something like: 
      $pages->find("template=project, tags=Experimental"); Only if the value (the page name, like "Experimental") starts with letters. If it starts with numbers, find returns nothing.
      Why is this and how can I fix it?
×
×
  • Create New...