Сортировать коллекцию по номерам, а затем по нулевым числам, используя laravel

У меня есть коллекция, в которой мне нужно упорядочить итоги (от низшего к высшему), и, если у клиента нет итога (-), оставьте его ниже клиентов, которые это делают.

Коллекция возвращает следующее:

введите здесь описание изображения

И мое намерение состоит в том, чтобы достичь следующего результата (сначала клиенты с итогом, а затем клиенты без итога):

введите здесь описание изображения

$sales = Sale::with('client')
         ->get()
         ->map(function($sale){
              $sale['total'] = $sale->total ? $sale->total * $sale->quantity : '--';
              return $sale;
         });

Я пытался использовать sortBy('total'), но у меня это не работает.

Решение:

    $sales = Sale::with('client')
         ->get()
         ->map(function($sale){
              $sale['total'] = $sale->total ? $sale->total * $sale->quantity : '--';
              return $sale;
         })
         ->sort(function($a, $b) {
            if ($a->total == "--" && $b->total != "--") {
                return 1;
            }
            if ($a->total != "--" && $b->total == "--") {
                return -1;
            }
            if ($a->total == "--" && $b->total == "--") {
                return 0;
            }
            return $a->total - $b->total;
        });

Спасибо за помощь. С уважением


person Cristian Meza    schedule 27.08.2018    source источник
comment
orderByRaw('-total DESC') попробуйте этот   -  person Marcus Stratu    schedule 27.08.2018
comment
Общее поле я создаю с помощью карты в коллекции, поэтому я не могу использовать orderBy. Спасибо.   -  person Cristian Meza    schedule 27.08.2018
comment
не могли бы вы показать нам, как выглядит ваша таблица (какие поля) sales и таблица clients?   -  person Vladyslav Startsev    schedule 28.08.2018


Ответы (2)


Вам просто нужно сделать заказ по возрастанию на awaitload :

$sales = Sale::select('total', 'client_id')
             ->with(['client'=>function($query){
                $query->orderBy('total', 'ASC');
            }])
        ->get();

отредактировано:

$sales = Sale::select('total', 'client_id') 
               ->with('client')
               ->orderBy('total', 'ASC')
               ->get();
person Leo    schedule 27.08.2018
comment
Поле total принадлежит таблице Sales, а не Clients. Спасибо - person Cristian Meza; 27.08.2018
comment
Применение orderBy не помогает, так как поле total получается внутри коллекции с помощью map. Я должен применить критерий порядка к коллекции, используя sortBy или sort. Спасибо - person Cristian Meza; 28.08.2018
comment
@CristianMeza затем добавьте весь запрос и модификацию с картой. - person Leo; 28.08.2018
comment
вложенный orderBy будет заказывать только по клиентам из каждой продажи. Не сами продажи. - person Mtxz; 28.08.2018
comment
@Leorent Изменить мой ответ - person Cristian Meza; 28.08.2018

Я думаю, вам нужно использовать SQL-соединение, если вы хотите упорядочить отношения, так как with() будет стремиться загрузить результат после (вы все равно можете использовать with(), если вам нужна активная загрузка клиентов).

Используйте СОЕДИНЕНИЕ

Sale::select('total', 'client_id')->join( 'client', 'client.sale_id', '=', 'sale.id' )>orderBy( 'client.total', 'ASC' )->get();

Не уверен насчет иностранных имен и прочего, но суть вы поняли.

Используйте сортировку (в вашей коллекции)

$data->sortBy('client.total');

Вы должны предпочесть решение 1 (JOIN), так как второму решению требуется запрос к базе данных + обработка коллекции.

Изменить: вы можете сделать более сложный оператор соединения

Edit2: проверьте этот стек

person Mtxz    schedule 27.08.2018
comment
Я не могу использовать соединение, так как общее поле я получаю в коллекции с помощью карты. Я должен применить порядок if или if к коллекции. Спасибо. - person Cristian Meza; 28.08.2018
comment
ааа да вижу. Итак, вам нужно отсортировать коллекцию после сопоставления. - person Mtxz; 28.08.2018