Jump to content

Siblings excluding current page


sw_double
 Share

Recommended Posts

Hello.

I'm really enjoying going into ProcessWire after using Drupal, CodeIgniter and FuelPHP for a while.

Anyway my first question is with this bit of code

$items = $page->siblings("template=portfolio-item, sort=random, path!={$page->path}");

As you can see, I'm trying to get siblings of the page, excluding current one.

But instead it returns ONLY current page, as if there was no exclamation mark in the path selector.

What's the problem here?

Update:

Okay, have found solution here http://processwire.com/talk/topic/1230-limit-siblings-after-removing-page/

Still curious about path selector behaviour though.

Link to comment
Share on other sites

Welcome to the forums sw_double!

I'll have to dig a bit deeper to find out why that doesn't work. By the looks of it it really should.

Meanwhile, this does the trick for you:

$items = $page->siblings("template=portfolio-item, sort=random, id!=$page");

Edit: Ah, I see you found the solution yourself already. I'm still interested in the actual cause, will come back later...

Link to comment
Share on other sites

Hi sw_double and welcome here :)

Not sure if this is causing the current output, but i think you can't say "sort=random", unless random would be a field defined on the portfoilo-item template. Maybe i'm wrong, but I haven't found this in the docs / cheatsheet.

Can you try with these lines?

//Find the siblings... leave away sort=random and path != {$page->path}
$items = $page->siblings("template=portfolio-item");

//If $items still contains the current page (not sure if this is by default...) -> remove it from $items
$items->remove($page);

//Get one random page
$random_item = $items->getRandom();

//Get multiple random pages
$count = count($items);
$random_items = $items->getRandom($count);
//or even better...
$random_items = $items->shuffle();

The cheatsheet is your best friend when it comes down to finding useful methods/properties :)

http://processwire.com/api/cheatsheet/

Cheers

Link to comment
Share on other sites

Not sure if this is causing the current output, but i think you can't say "sort=random", unless random would be a field defined on the portfoilo-item template. Maybe i'm wrong, but I haven't found this in the docs / cheatsheet.

You can say sort=random, both for database operations ($pages->find/get) and PageArray operations (find/get/sort). See https://github.com/r...Finder.php#L490 and https://github.com/r...Array.php#L681.

I tried that "path!=..." selector out and was able to reproduce the problem as described.

  • Like 1
Link to comment
Share on other sites

Thank you guys for quick response and warm welcome.

There might be a bug with path!= selector.

Little additional question.

I want to get say five closest siblings (which would be two prevs, self and two nexts OR if the page is first then it would be self and four nexts etc). Is there any shortcut for this logic in the API? Anything like ->closest(5) or at least ->next(2)?

If not please consider it a feature request as it feels like common logic required.

  • Like 1
Link to comment
Share on other sites

I think it's already on ryan's radar after a similar discussion about closest parents with selectors and I'm sure he'll also weigh in on this idea too as it seems like at the very least you wouldn't want the two to be called "closest" and do two different things!

You almost want it to be $pages->closest("id=$page")->siblings(5); or something like that.

Link to comment
Share on other sites

There might be a bug with path!= selector.

Yes, looks like it. The method handling 'path' and 'url' in selectors (https://github.com/ryancramerdesign/ProcessWire/blob/master/wire/core/PageFinder.php#L572) doesn't check which operator was used, but assumes it was '='. At least it should raise an exception if an unsupported operator was used.

I think Ryan will spot this from here.

I want to get say five closest siblings (which would be two prevs, self and two nexts OR if the page is first then it would be self and four nexts etc). Is there any shortcut for this logic in the API? Anything like ->closest(5) or at least ->next(2)?

There are methods next() and prev() for a page. They only give you one page in each direction (if one exists) but it shouldn't bee too hard to implement what you we're asking for using those. But do consider Ryan's comment in the source: "Be careful with this function when the page has a lot of siblings. It has to load them all, so this function is best avoided at large scale, unless you provide your own already-reduced siblings list (like from pagination).

Link to comment
Share on other sites

You can't use any operator except '=' when querying path or url from the database (like when using $pages->find). This is because the path doesn't actually exist in the database, so there's nothing to perform comparisons on. It is generated at runtime based on a page combining its name with the names of its parents. It worked with '=' because we pulled a few tricks to convert a path into a big left join statement, in an attempt to match it. And this actually works very well. But it doesn't translate quite as well to other operators. 

I should have had the engine throw an exception when you used an operator it didn't support for that. Instead it just switched it to an '='. So I've updated it so that it now throws an exception instead. 

I've also added a new module to the core, called PagePaths. When you grab the latest dev branch, do a 'check for new modules' and you should see it. Once you install that, it goes and sets up a table with all the page paths and a means of querying them. This enables you to use any operator when querying path or url, including all the partial text matching ones like %=, *=, ~=, ^=, $=. As a side effect, this module also brings potential performance improvements to other queries, as  it eliminates the need for the left join trick I mentioned above. (Though in my initial tests, it doesn't seem to be a measurable improvement). I will probably have this module installed by default for new installations of 2.3. But won't have it auto-install to existing installations. That's because it has to generate an index of all pages in your site--a potentially resource consuming process. For instance, Antti's 100k page site probably won't work with this, as it's no small task to go and build an index for 100k pages after the fact. But if you aren't running a massive site already, this module is one you probably want on most sites, so I went ahead and included it in the core. 

  • Like 4
Link to comment
Share on other sites

  • 5 years later...

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...