sortBy callback method

I want to sort users with handle field.

For ex: users have “currency (2.3)” and “price (40)” field and i will sort by “currency x price (92)”.

sortBy function no support callback. How can i do that?

Thanks

The sortBy() methods supports sorting by multiple fields, here’s the example from the docs:

<?php
$articles = page('blog')->children()->sortBy('date', 'desc', 'time', 'asc');
?>

Not sure if this works with users as well, but it should …

I expecting merging fields not multiple sorting. How multiply currency and price? like that: sortBy('currency*price', 'desc') :wink:

This kind of field is considered a “computed” field. These are best stored in page models:

// site/models/article.php

class ArticlePage extends Page
{
    public function computed()
    {
        return (float) ($this->currency()->value() * $this->price()->value());
    }
}

Now that you have a field for your calculation, you can use sortBy on the collection.

$articles = page('blog')->children()->sortBy('computed', 'asc');
1 Like

It’s worth noting that you can also use this field in your templates. You can use it anytime you’re working with a Page of type article.

// templates/article.php
<?php echo $page->computed() ?>
// templates/blog.php
<?php foreach ($page->children() as $article): ?>
    <div>
        Your price: <?php echo $article->computed() ?>
    </div>
<?php endforeach ?>
1 Like

Great solution but this is not page :frowning: Sorting users…
Users not supports model, right?

Oops, you’re right.

I have come across a few similar situations where I wish Kirby supported User models.

I have another idea… checking on it now.

2 Likes

You could, however, create a hook (panel.user.update) that calculates your product and writes it to a hidden/readonly field in the user text file.

1 Like

I was just thinking the same thing as @texnixe just mentioned…

Since your fields are both stored statically in the user’s account file, there’s no reason you can’t store the calculated value in the file, as well, then use it for sorting.

And to save yourself the trouble of manually calculating it each time you modify price or currency, use a panel hook to automatically calculate and store it for you.

But another option is to loop through users and save the username and the calculated value in an array. Then sort that array by the calculated value. Then loop through the usernames, loading each user by name inside the loop.

@texnixe’s solution sensible until upcoming callback feature on new version :wink:

@jevets I will think that saving calculated value. I think good idea but have to look forward to whether will bug or not.

Thanks for great solutions @jevets and @texnixe