Skip to content

Commit 5ba7984

Browse files
committedNov 19, 2020
Merge branch 'johnylemon/8.x' into 8.x
2 parents c054535 + 53eb307 commit 5ba7984

File tree

3 files changed

+103
-2
lines changed

3 files changed

+103
-2
lines changed
 

‎src/Illuminate/Collections/Arr.php

+1-1
Original file line numberDiff line numberDiff line change
@@ -604,7 +604,7 @@ public static function shuffle($array, $seed = null)
604604
* Sort the array using the given callback or "dot" notation.
605605
*
606606
* @param array $array
607-
* @param callable|string|null $callback
607+
* @param callable|array|string|null $callback
608608
* @return array
609609
*/
610610
public static function sort($array, $callback = null)

‎src/Illuminate/Collections/Collection.php

+49-1
Original file line numberDiff line numberDiff line change
@@ -1110,13 +1110,17 @@ public function sortDesc($options = SORT_REGULAR)
11101110
/**
11111111
* Sort the collection using the given callback.
11121112
*
1113-
* @param callable|string $callback
1113+
* @param callable|array|string $callback
11141114
* @param int $options
11151115
* @param bool $descending
11161116
* @return static
11171117
*/
11181118
public function sortBy($callback, $options = SORT_REGULAR, $descending = false)
11191119
{
1120+
if (is_array($callback)) {
1121+
return $this->sortByMany($callback);
1122+
}
1123+
11201124
$results = [];
11211125

11221126
$callback = $this->valueRetriever($callback);
@@ -1141,6 +1145,50 @@ public function sortBy($callback, $options = SORT_REGULAR, $descending = false)
11411145
return new static($results);
11421146
}
11431147

1148+
/**
1149+
* Sort the collection using multiple comparisons.
1150+
*
1151+
* @param array $comparisons
1152+
* @return static
1153+
*/
1154+
protected function sortByMany(array $comparisons = [])
1155+
{
1156+
$items = $this->items;
1157+
1158+
usort($items, function ($a, $b) use ($comparisons) {
1159+
foreach ($comparisons as $comparison) {
1160+
$comparison = Arr::wrap($comparison);
1161+
1162+
$prop = $comparison[0];
1163+
1164+
$ascending = Arr::get($comparison, 1, true) === true ||
1165+
Arr::get($comparison, 1, true) === 'asc';
1166+
1167+
$result = 0;
1168+
1169+
if (is_callable($prop)) {
1170+
$result = $prop($a, $b);
1171+
} else {
1172+
$values = [Arr::get($a, $prop), Arr::get($b, $prop)];
1173+
1174+
if (! $ascending) {
1175+
$values = array_reverse($values);
1176+
}
1177+
1178+
$result = $values[0] <=> $values[1];
1179+
}
1180+
1181+
if ($result === 0) {
1182+
continue;
1183+
}
1184+
1185+
return $result;
1186+
}
1187+
});
1188+
1189+
return new static($items);
1190+
}
1191+
11441192
/**
11451193
* Sort the collection in descending order using the given callback.
11461194
*

‎tests/Support/SupportArrTest.php

+53
Original file line numberDiff line numberDiff line change
@@ -903,4 +903,57 @@ public function testWrap()
903903
$this->assertEquals([$obj], Arr::wrap($obj));
904904
$this->assertSame($obj, Arr::wrap($obj)[0]);
905905
}
906+
907+
public function testSortByMany()
908+
{
909+
$unsorted = [
910+
['name' => 'John', 'age' => 8, 'meta' => ['key' => 3]],
911+
['name' => 'John', 'age' => 10, 'meta' => ['key' => 5]],
912+
['name' => 'Dave', 'age' => 10, 'meta' => ['key' => 3]],
913+
['name' => 'John', 'age' => 8, 'meta' => ['key' => 2]],
914+
];
915+
916+
// sort using keys
917+
$sorted = array_values(Arr::sort($unsorted, [
918+
'name',
919+
'age',
920+
'meta.key',
921+
]));
922+
$this->assertEquals([
923+
['name' => 'Dave', 'age' => 10, 'meta' => ['key' => 3]],
924+
['name' => 'John', 'age' => 8, 'meta' => ['key' => 2]],
925+
['name' => 'John', 'age' => 8, 'meta' => ['key' => 3]],
926+
['name' => 'John', 'age' => 10, 'meta' => ['key' => 5]],
927+
], $sorted);
928+
929+
// sort with order
930+
$sortedWithOrder = array_values(Arr::sort($unsorted, [
931+
'name',
932+
['age', false],
933+
['meta.key', true],
934+
]));
935+
$this->assertEquals([
936+
['name' => 'Dave', 'age' => 10, 'meta' => ['key' => 3]],
937+
['name' => 'John', 'age' => 10, 'meta' => ['key' => 5]],
938+
['name' => 'John', 'age' => 8, 'meta' => ['key' => 2]],
939+
['name' => 'John', 'age' => 8, 'meta' => ['key' => 3]],
940+
], $sortedWithOrder);
941+
942+
// sort using callable
943+
$sortedWithCallable = array_values(Arr::sort($unsorted, [
944+
function ($a, $b) {
945+
return $a['name'] <=> $b['name'];
946+
},
947+
function ($a, $b) {
948+
return $b['age'] <=> $a['age'];
949+
},
950+
['meta.key', true],
951+
]));
952+
$this->assertEquals([
953+
['name' => 'Dave', 'age' => 10, 'meta' => ['key' => 3]],
954+
['name' => 'John', 'age' => 10, 'meta' => ['key' => 5]],
955+
['name' => 'John', 'age' => 8, 'meta' => ['key' => 2]],
956+
['name' => 'John', 'age' => 8, 'meta' => ['key' => 3]],
957+
], $sortedWithCallable);
958+
}
906959
}

0 commit comments

Comments
 (0)