oma

Sort pages by exploded string result

Recommended Posts

Hi folks,

I have a list of people as pages, with the titles, for example, Joe Bloggs, Adam Whyte, Paul Simants).

I don't want to have three fields (one for title, one for first name and one for second) to be able to sort by last name... it seems a bit overkill. I reckon I could explode the string and use the last word to sort by (won't work in all cases but could do... or at least everything from first word onwards) but I have two questions...

1. Do you think it's possible to use this exploded result in the selector as a sort option?

2. Is there a way to hook into the sort order for these pages in the backend (Template > Family > Sort settings for children) by using the same exploded result? Rather than what's predefined in the dropdown (the fields).

Share this post


Link to post
Share on other sites

From what you're describing I would go with creating those 3 fields. It's not really overkill (in which terms do you think it would be overkill?) and makes your life so much simpler.

What you're thinking of doing sounds really hacky, and usually with hacky solutions you will have trouble in the end.

  • Like 4

Share this post


Link to post
Share on other sites
12 hours ago, MrSnoozles said:

From what you're describing I would go with creating those 3 fields. It's not really overkill (in which terms do you think it would be overkill?) and makes your life so much simpler.

What you're thinking of doing sounds really hacky, and usually with hacky solutions you will have trouble in the end.

Okay! Cool! I just wanted to make sure there wasn't a better way. Thanks!

Share this post


Link to post
Share on other sites

I'm in a situation where it would be overkill to create new fields.

Currently, I'm facing the same problem, having a title field width full names that I'd like to sort by the last name. So is there an answer to the first question of @oma, without creating separate fields?

Share this post


Link to post
Share on other sites

To be honest, after a lot of searching, I can't really find any clean way of doing this that isnt hacky. I know with explode you can do: 

$name = "John Doe";
$chunks = explode(" ", $name);

echo $chunks[1];

However, I dont think you can really apply this to $pages->find() as it returns a PageArray and not a string which you would need for explode. If you have access to it, the Profields module "Textareas" allows you to have one field, but define multiple fields through it: ie first_name and last_name. 

Share this post


Link to post
Share on other sites

Thanks for your reply, Louis!
I just want a DRY approach. I have a list of team members, all saved as single pages in PW. When adding a new member, I create a new page and put the full name into the title, so I have the name already there, for the URL and for output in the frontend. Now, I don't want to have to input the same name again in further fields like first_name and last_name, just to be able to sort by last_name. This should be possible in an easier way.

Quote

However, I dont think you can really apply this to $pages->find() as it returns a PageArray and not a string which you would need for explode. 

I could get the names with:

$names = $pages->get("name=parentpage")->children->title;

Then I could loop through the array and explode the names to get the last name.

But then I'm to much of a PHP noob to use the result as a property to sort the pages.

I guess there must be a PHP way to get there, something like usort() or array_multisort(), but – at least for me – to complicated …

Share this post


Link to post
Share on other sites

I didn't find a solution to use the exploded full name as a sort string for sorting by last_name, so I put a separate last_name field into the template that ist only used for sorting. As I don't want users to fill in the name twice, I did that automatically by checking if the last_name is empty when loading the team page on the frontend.

I added this code at the top of the teams template, that is showing all the team members

$team_members = $pages->find("template=team_member, last_name=''");
foreach($team_members as $team_member) {
    $name = explode(" ", $team_member->title);
    $team_member->of(false); // "turns off output formatting"
    $team_member->last_name = $name[1];
    $team_member->save();
}

Now, when I load the page in the front end, the last name is saved into the database and can be used for sorting.
I'm fine with this workaround, maybe it is useful for someone else 🙂

Share this post


Link to post
Share on other sites
On 7/11/2018 at 10:16 PM, Christoph said:

I'm in a situation where it would be overkill to create new fields.

It's never overkill to create the fields you need to achieve the functionality you want. For efficiency PW sorts pages when it gets them in the SQL query. So when you get pages from the database whatever you want to sort on must exist as a column in the database. You can sort a PageArray independently of this but it's less efficient and will be problematic when you have a large number of pages or want to add pagination to your results. Also, think about the sorting of names like "Anthony van Diemen" if you were to try to sort without an explicit "last name" field.

 

17 hours ago, Christoph said:

When adding a new member, I create a new page and put the full name into the title, so I have the name already there, for the URL and for output in the frontend. Now, I don't want to have to input the same name again in further fields like first_name and last_name, just to be able to sort by last_name.

There is no need to enter anything twice. There are a few different ways you could go about it - here is the one that I prefer because it's simple and intuitive even if it does involve some minor redundancy of data...

This assumes you have a template team_members that allows children of template team_member.

1. Install the core PagePathHistory module if you haven't already (a must-have for every site).

2. Install the Page Rename Options module.

3. Add text fields first_name and last_name to template team_member, right after the title field. Make them required fields, and a width of 50% would make sense.

4. In template team_member re-label the title field to "Full name" and set the field visibility to "Open when populated + Closed when blank + Locked (not editable)".

5. In the Family tab of template team_members set "Name format for children" to "Y/m/d H:i:s". This allows new pages added under this template to skip the first step of the "Add New" process. New pages will get a name according to the date/time they were added but this is only temporary until they are published or saved for the first time.

6. Add the following hook to /site/ready.php

$pages->addHookAfter('saveReady', function(HookEvent $event) {
    $page = $event->arguments(0);
    // Only for the team_member template
    if($page->template != 'team_member') return;
    // Skip if this page is brand new and doesn't have any data yet
    if(!$page->id) return;

    // Derive the title (Full name) from the first_name and last_name fields
    // The Page Rename Options module will take care of updating the page name to match
    $page->title = $page->first_name . ' ' . $page->last_name;
});

Now in your template files you can get and sort on the first_name and last_name fields independently. If you want the full name you could output those fields together, but why bother when you also have the full name in the title field. Having the full name in the title field is nice because things in the PW admin (Page List, Page Edit headings, admin search) continue to work without needing any special settings or additional hooks.

Edited by Robin S
Removed unrelated screenshot.
  • Like 8

Share this post


Link to post
Share on other sites

Hi Robin, 

this is just great, thanks a lot!

Yes, it's the best way to have first_name and last_name as separated fields, but up until now I had no idea how to automatically combine and use them for the title.
Will try this.

Share this post


Link to post
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

  • Recently Browsing   0 members

    No registered users viewing this page.