Jump to content

$pages->find() get by id and maintain order


Torsten Baldes
 Share

Recommended Posts

Hi,

I have multiple $pages->find() operations which result in multiple page ids.

e.g.: 

$find1: 8044|10045|3702|11067
$find2: 2004|5421|9392

Next i'm searching these ids to get a new WireArray, which i can limit and paginate:

$unifiedMatches = $pages->find("id=$find1|$find2, limit=$limit");

This works all as intended. The problem is, that this new collection of pages doesn't maintain the order of the ids in the selector. They are sorted by their id.

$unifiedMatches: 2004|3702|5421|8044|9392|10045|11067

Is there a way to get the pages in the $unifiedMatches result in the order of the selector input?

$unifiedMatches: 8044|10045|3702|11067|2004|5421|9392

Thanks!

  • Like 2
Link to comment
Share on other sites

Hi Torsten

thanks for the question, I also stumbled upon this problem and couldn't find a solution so far. There are simple solutions in ExpressionEngine and Craft (https://docs.expressionengine.com/latest/channels/entries.html#fixed_order, https://docs.craftcms.com/v3/dev/element-queries/entry-queries.html#fixedorder), maybe I missed something.

Here's a workaround, temporary test code from a current project:

$itemIdsA ia an array of ids, $finder3A is an array with results from a rockfinder query.

if(count($itemIdsA)) {
	foreach($itemIdsA as $key => $value) {
		foreach($finder3A as $item) {
			if($value == $item['id']) {
				echo '<li>';
				$datumVon = strtotime($item['datum_von']);
				echo 'Autor: ' . $item['autoren_title'] . ' / Datum: ' . date('d.m.Y H:i', $datumVon) . '<br />';
				echo '<h3>' . $item['title'] . '</h3>';
				echo '<p>' . $item['teaser'] . '</p>';
				if(isset($pma[$item['id']])){
					echo '<p>Test Anzahl Leserbriefe: ' . $pma[$item['id']][0] . '</p>';
				}
				echo '</li>';
			}
		}
	}
}

 

  • Like 1
Link to comment
Share on other sites

Thanks,

but I'm afraid this doesn't work with pagination.

At first I created a new wirearray and added the others. This worked regarding maintaining the order, but got me problems with the pagination. Your approach would possibly work too, but I would have the same pagination trouble. ?

Link to comment
Share on other sites

2 hours ago, Torsten Baldes said:

$unifiedMatches = $pages->find("id=$find1|$find2, limit=$limit");

 

Did you try someting like

$unifiedMatches = $pages->find("id=$find1, limit=$limit")->add($pages->find("id=$find2, limit=$limit"));

? Seems to work with a quick test here...

Link to comment
Share on other sites

My workaround was because of unsorted query results from a Page Reference field inside a Repeater Matrix field. If you can use $pages->find(), the results should get sorted: Try loadOptions and set joinSortfield to true. Test:

$items = $pages->getById([1182,1061,1079,1082]);
d($items);

The result is a PageArray, the items => array is sorted in the order of the ids in your selector.

Update: It doesn't seem to work with $pages->find(), but you can use $pages->getById.

Edited by Lutz
update
  • Like 1
  • Thanks 1
Link to comment
Share on other sites

11 minutes ago, bernhard said:

So what are your finds sorted by? Could you share those find queries with us?

The sorting of these queries is not really important. The important thing for me is, that the results from $find1 are in front of $find2.

It's like a lazy weighted search, where I first search the titles of the pages for a keyword/phrase ($find1) and then search the other fields (body etc.) for the same keyword (excluding the ids from $find1). The logic here is, that pages, which have the keyword in their title, are more relevant/important than the other results and should come first.

  • Like 1
Link to comment
Share on other sites

12 minutes ago, Torsten Baldes said:

It's like a lazy weighted search, where I first search the titles of the pages for a keyword/phrase ($find1) and then search the other fields (body etc.) for the same keyword (excluding the ids from $find1). The logic here is, that pages, which have the keyword in their title, are more relevant/important than the other results and should come first.

Thx for clarifying, that makes things clear but complicated ? 

I don't think that there is a way to achieve this on the db side. Only chance is on the PHP side. Does something like this work?

 

Link to comment
Share on other sites

  • 2 years later...
On 7/18/2019 at 5:30 AM, Torsten Baldes said:

@dragan @bernhard

Yes adding works to get a "unified" PageArray with the right order, but the pagination for this remains empty.

$unifiedMatches = $find1->add($find2)->find("limit=$limit");

$unifiedMatches->renderPager() returns nothing.

I'm facing a similar issue (and overall trying to achieve something similar to your original post).  I'm not sure if it's a bug but I filed an Issue:
https://github.com/processwire/processwire-issues/issues/1477

Link to comment
Share on other sites

As of today's latest commit to the dev branch, the solution to the original question of sorting results by a specific order of page IDs is now possible.

// get page 2, then 1, then 3 in that specific order using the new 'id.sort'; you can also use "limit" for pagination without any downsides
$pages->find("id.sort=2|1|3");

More info: https://github.com/processwire/processwire-issues/issues/1477#issuecomment-982928688

  • Like 6
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

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...