1

i have some issues with laravel sortBy ( laravel 5.4 ) .. based on what i read on many websites, it says that for doing multiple sortBy laravel was by using reverse order.. so i try to do that.. but still not working properly..

So here it is.. I have this collection of object...

[{
   'product_id' => 468,
   'name' => 'abc',
   'int_premi' => 10000
   'score' => 1000
   'rates' => 0,
   'views' => 0,
   'promo' => null
},{
   'product_id' => 472,
   'name' => 'bcd',
   'int_premi' => 10000
   'score' => 1000
   'rates' => 0,
   'views' => 0,
   'promo' => 'Some text here'
},{
   'product_id' => 458,
   'name' => 'def',
   'int_premi' => 10000
   'score' => 1000
   'rates' => 0,
   'views' => 0,
   'promo' => 'ABC'
}]

My Goal is to have this objects sorted following this order

score ( asc ) > int_premi ( asc ) > rates ( desc ) > promo ( as boolean ) ( desc ) > views ( desc ) > product_id ( desc )

So i write this code..

$collection->sortByDesc('product_id')->sortByDesc('views')->sortByDesc(function($arr,$k){
                            return !empty($arr->promo);
    })->sortByDesc('rates')->sortBy('int_premi')->sortBy('score')->values()->all()

I'm looking for the result comes with this order

BCD > DEF > ABC

Instead, not following that order..

So is there anyone also facing the same issue with me ? and maybe someone can help me out through this issue ?

Thankyou Very much

7
  • Did you read github.com/laravel/ideas/issues/11? Commented May 10, 2018 at 14:24
  • Just did, so this is bug from laravel ? Commented May 10, 2018 at 14:51
  • 1
    The cause is rather the underlying PHP function. Does the workaround in the second to last comment help you? Commented May 10, 2018 at 15:24
  • As @JonasStaudenmeir stated this comes with underlying PHP functions and unfortunately causes severe problems, while fiddling with different php versions. There were attempts, to solve it in laravel 5.5, but you are on 5.4. Check what php version you are running and then check how asort and arsort functions are working on your server to find out your desired behaviour. And finally, what I may advise, write unit test to check, if it is working in your app. Then while changing environment, you will know if there is a need to modify some things. I know this does not feel even close to optimal :( Commented May 10, 2018 at 22:04
  • Thankyou guys for replying my questions.. i have found the solution.. i also put it on this question answer.. so other people who face this problem might able to solve their issues.. thankyou.. Commented May 15, 2018 at 6:18

3 Answers 3

3

After doing some research.. i found the one is working.. If you are facing the same thing.. this article might help..

https://www.jjanusch.com/2017/05/laravel-collection-macros-adding-a-sortbymuti-function

So my final is exact same thing with this article suggestion, by creating a macro.. like this

if (!Collection::hasMacro('sortByMulti')) {
    /**
     * An extension of the {@see Collection::sortBy()} method that allows for sorting against as many different
     * keys. Uses a combination of {@see Collection::sortBy()} and {@see Collection::groupBy()} to achieve this.
     *
     * @param array $keys An associative array that uses the key to sort by (which accepts dot separated values,
     *                    as {@see Collection::sortBy()} would) and the value is the order (either ASC or DESC)
     */
    Collection::macro('sortByMulti', function (array $keys) {
        $currentIndex = 0;
        $keys = array_map(function ($key, $sort) {
            return ['key' => $key, 'sort' => $sort];
        }, array_keys($keys), $keys);

        $sortBy = function (Collection $collection) use (&$currentIndex, $keys, &$sortBy) {
            if ($currentIndex >= count($keys)) {
                return $collection;
            }

            $key = $keys[$currentIndex]['key'];
            $sort = $keys[$currentIndex]['sort'];
            $sortFunc = $sort === 'DESC' ? 'sortByDesc' : 'sortBy';
            $currentIndex++;
            return $collection->$sortFunc($key)->groupBy($key)->map($sortBy)->ungroup();
        };

        return $sortBy($this);
    });
}

Then you can just using it on your collection like this

$collection->sortByMulti([
    'prop_one'       => 'ASC',
    'prop_two'        => 'ASC',
    etc....
]);

prop_one and prop_two is your collection properties.. Hope this help

Sign up to request clarification or add additional context in comments.

1 Comment

I've tried this solution and is was showing me that the ungroup method did not exist, is is also another macro, you can find the whole code here: github.com/bayareawebpro/laravel-examples/blob/master/…
0

This code works just fine according to your need. But if you want to modify something, you can comment:

$collection = ([[
   'product_id' => 468,
   'name' => 'abc',
   'int_premi' => 10000,
   'score' => 1000,
   'rates' => 0,
   'views' => 0,
   'promo' => null
],[
   'product_id' => 472,
   'name' => 'bcd',
   'int_premi' => 10000,
   'score' => 1000,
   'rates' => 0,
   'views' => 0,
   'promo' => 'Some text here'
],[
   'product_id' => 458,
   'name' => 'def',
   'int_premi' => 10000,
   'score' => 1000,
   'rates' => 0,
   'views' => 0,
   'promo' => 'ABC'
]]);

$collection = collect($collection)->sortByDesc('product_id')->sortByDesc('views')->sortByDesc('promo')->sortByDesc('rates')->sortBy('int_premi')->sortBy('score')->values()->all();
return $collection;

Comments

0

It is already working:

$collection->sortBy([
    ['rates', 'desc'],
    ['int_premi', 'asc'],
    ['score', 'asc'],
]);

That is it.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.