Sort by order of the items listed in the blueprint

I want to be able to sort by the order of the way they are defined inside the blueprint.

employee.yml

      # position
      position:
        type: select
        label:
          en: Position
          de: Position
        required: true
        options:
          ceo:
            en: CEO
            de: CEO
          director:
            en: Director
            de: Director
          design:
            en: Graphic Designer
            de: Graphic Designer

Which means I want to be able to display the out of this on the front-end as such - CEO, Director, Graphic Designer.

Currently I have this but the order is wrong

controllers/about.php

$members = $page->children()->listed()->sortBy(function ($page) {
    return $page->position();
});

templates/about.php

<?php foreach($members as $member): ?>
    <div>
        <a href="<?= $member->url() ?>"><?= $member->headline()->or($member->title()) ?></a>
        <p><?= $member->position() ?></p>
    </div>
<?php endforeach ?>

The order is being output as such - CEO, Graphic Design, Director

Try:

$members = $page->children()->listed()->sortBy(function ($page) {
   $order = ['ceo' => 1, 'director' => 2, 'design' => 3];
    return $order[$page->position()->value()];
});

Yes that works but is there anyway I could automatically generate this line?

$order = ['ceo' => 1, 'director' => 2, 'design' => 3];

You would have to read the options from the blueprint, but I wonder if that’s worth it. After all, these options don’t have an inherent order but just the one you defined in your blueprint.

Maybe set up your array of options somewhere and query that in your field so that you can then reuse that in your template code.

Need to ask a new question on this one - how would I sort by the $order = ['ceo' => 1, 'director' => 2, 'design' => 3] and the sort order from the panel?

Meaning it will return users in the specified order of CEO, Director, Design etc… but the members in each of these to be ordered by the panel order.

Example

1 - stephen - CEO
2 - ken - CEO
3 - fake - design
4 - joe - director

Current Output

2 - ken - CEO
1 - stephen - CEO
4 - joe - director
3 - fake - design

Desired Output

1 - stephen - CEO
2 - ken - CEO
4 - joe - director
3 - fake - design

By what do you sort in the Panel?

For example stephen & ken are CEO’s but stephen is like the founding CEO or highest stake holder so should always appear first in the sequence.

Be that as it may, but there must be some criterion that makes this Stephen the super hero in the Panel? Default sorting order by number?

Oh yes - sorry in my example above the numbers where the ordering from the panel. It’s just the default number ordering yes.

Sorry - I thought you were asking but why, haha…

$members = $page->children()->listed()->sortBy(function ($page) {
   $order = ['ceo' => 1, 'director' => 2, 'design' => 3];
    return $order[$page->position()->value()];
})->sortBy('num', 'asc');

Oh, ok. I thought I would need to do something fancy with the sortBy option, didn’t realise I could have two of them.

Never mind - it breaks. @texnixe

If I move

4 - fake - design

above

3 - joe - director

the sorting on the front-end now sorts by only the num and not take into consideration the group order anymore.

Meaning I am now getting this output

1 - stephen - CEO
2 - ken - CEO
3 - fake - design
4 - joe - director

And not the desired output of

1 - stephen - CEO
2 - ken - CEO
4 - joe - director
3 - fake - design

It no longer respects the $order = ['ceo' => 1, 'director' => 2, 'design' => 3];

You can sort by as many criteria as you like or as it makes sense.

Hm, but the group sorting should come before the number sorting… Have to test this.

Yes but I thought it had to be like this

->sortBy('itemDate', 'desc', 'itemTime', 'desc');

I didn’t realise I could go

->sortBy()->sortBy()

Which is why I asked the question

Controller

<?php

return function ($page) {

    $members = $page->children()->listed()->sortBy(function ($page) {

        $order = ['ceo' => 1, 'director' => 2, 'design' => 3];

        return $order[$page->position()->value()];

    })->sortBy('num', 'asc');

    return [
        'members' => $members
    ];

};

Template

<?php foreach($members as $member): ?>
    <div>
        <a href="<?= $member->url() ?>">
            <?= $member->headline()->or($member->title()) ?>
        </a>
        <p><?= $member->position() ?></p>
    </div>
<?php endforeach ?>

@texnixe

So doing this fixes it out of interest

$members = $page->children()->listed()->sortBy(function ($page) {

        $order = ['ceo' => 1, 'director' => 2, 'design' => 3];

        return $order[$page->position()->value()];

    }, 'num', 'asc');

Ok, even better.