composer package updates
[openemr.git] / vendor / illuminate / support / Collection.php
blob38dd526f0365bb9c42504c7a868e28157e231d07
1 <?php
3 namespace Illuminate\Support;
5 use stdClass;
6 use Countable;
7 use Exception;
8 use ArrayAccess;
9 use Traversable;
10 use ArrayIterator;
11 use CachingIterator;
12 use JsonSerializable;
13 use IteratorAggregate;
14 use Illuminate\Support\Debug\Dumper;
15 use Illuminate\Support\Traits\Macroable;
16 use Illuminate\Contracts\Support\Jsonable;
17 use Illuminate\Contracts\Support\Arrayable;
19 class Collection implements ArrayAccess, Arrayable, Countable, IteratorAggregate, Jsonable, JsonSerializable
21 use Macroable;
23 /**
24 * The items contained in the collection.
26 * @var array
28 protected $items = [];
30 /**
31 * The methods that can be proxied.
33 * @var array
35 protected static $proxies = [
36 'average', 'avg', 'contains', 'each', 'every', 'filter', 'first', 'flatMap',
37 'keyBy', 'map', 'partition', 'reject', 'sortBy', 'sortByDesc', 'sum', 'unique',
40 /**
41 * Create a new collection.
43 * @param mixed $items
44 * @return void
46 public function __construct($items = [])
48 $this->items = $this->getArrayableItems($items);
51 /**
52 * Create a new collection instance if the value isn't one already.
54 * @param mixed $items
55 * @return static
57 public static function make($items = [])
59 return new static($items);
62 /**
63 * Wrap the given value in a collection if applicable.
65 * @param mixed $value
66 * @return static
68 public static function wrap($value)
70 return $value instanceof self
71 ? new static($value)
72 : new static(Arr::wrap($value));
75 /**
76 * Get the underlying items from the given collection if applicable.
78 * @param array|static $value
79 * @return array
81 public static function unwrap($value)
83 return $value instanceof self ? $value->all() : $value;
86 /**
87 * Create a new collection by invoking the callback a given amount of times.
89 * @param int $number
90 * @param callable $callback
91 * @return static
93 public static function times($number, callable $callback = null)
95 if ($number < 1) {
96 return new static;
99 if (is_null($callback)) {
100 return new static(range(1, $number));
103 return (new static(range(1, $number)))->map($callback);
107 * Get all of the items in the collection.
109 * @return array
111 public function all()
113 return $this->items;
117 * Get the average value of a given key.
119 * @param callable|string|null $callback
120 * @return mixed
122 public function avg($callback = null)
124 if ($count = $this->count()) {
125 return $this->sum($callback) / $count;
130 * Alias for the "avg" method.
132 * @param callable|string|null $callback
133 * @return mixed
135 public function average($callback = null)
137 return $this->avg($callback);
141 * Get the median of a given key.
143 * @param null $key
144 * @return mixed
146 public function median($key = null)
148 $count = $this->count();
150 if ($count == 0) {
151 return;
154 $values = (isset($key) ? $this->pluck($key) : $this)
155 ->sort()->values();
157 $middle = (int) ($count / 2);
159 if ($count % 2) {
160 return $values->get($middle);
163 return (new static([
164 $values->get($middle - 1), $values->get($middle),
165 ]))->average();
169 * Get the mode of a given key.
171 * @param mixed $key
172 * @return array|null
174 public function mode($key = null)
176 $count = $this->count();
178 if ($count == 0) {
179 return;
182 $collection = isset($key) ? $this->pluck($key) : $this;
184 $counts = new self;
186 $collection->each(function ($value) use ($counts) {
187 $counts[$value] = isset($counts[$value]) ? $counts[$value] + 1 : 1;
190 $sorted = $counts->sort();
192 $highestValue = $sorted->last();
194 return $sorted->filter(function ($value) use ($highestValue) {
195 return $value == $highestValue;
196 })->sort()->keys()->all();
200 * Collapse the collection of items into a single array.
202 * @return static
204 public function collapse()
206 return new static(Arr::collapse($this->items));
210 * Determine if an item exists in the collection.
212 * @param mixed $key
213 * @param mixed $operator
214 * @param mixed $value
215 * @return bool
217 public function contains($key, $operator = null, $value = null)
219 if (func_num_args() == 1) {
220 if ($this->useAsCallable($key)) {
221 $placeholder = new stdClass;
223 return $this->first($key, $placeholder) !== $placeholder;
226 return in_array($key, $this->items);
229 return $this->contains($this->operatorForWhere(...func_get_args()));
233 * Determine if an item exists in the collection using strict comparison.
235 * @param mixed $key
236 * @param mixed $value
237 * @return bool
239 public function containsStrict($key, $value = null)
241 if (func_num_args() == 2) {
242 return $this->contains(function ($item) use ($key, $value) {
243 return data_get($item, $key) === $value;
247 if ($this->useAsCallable($key)) {
248 return ! is_null($this->first($key));
251 return in_array($key, $this->items, true);
255 * Cross join with the given lists, returning all possible permutations.
257 * @param mixed ...$lists
258 * @return static
260 public function crossJoin(...$lists)
262 return new static(Arr::crossJoin(
263 $this->items, ...array_map([$this, 'getArrayableItems'], $lists)
268 * Dump the collection and end the script.
270 * @return void
272 public function dd(...$args)
274 http_response_code(500);
276 call_user_func_array([$this, 'dump'], $args);
278 die(1);
282 * Dump the collection.
284 * @return $this
286 public function dump()
288 (new static(func_get_args()))
289 ->push($this)
290 ->each(function ($item) {
291 (new Dumper)->dump($item);
294 return $this;
298 * Get the items in the collection that are not present in the given items.
300 * @param mixed $items
301 * @return static
303 public function diff($items)
305 return new static(array_diff($this->items, $this->getArrayableItems($items)));
309 * Get the items in the collection whose keys and values are not present in the given items.
311 * @param mixed $items
312 * @return static
314 public function diffAssoc($items)
316 return new static(array_diff_assoc($this->items, $this->getArrayableItems($items)));
320 * Get the items in the collection whose keys are not present in the given items.
322 * @param mixed $items
323 * @return static
325 public function diffKeys($items)
327 return new static(array_diff_key($this->items, $this->getArrayableItems($items)));
331 * Execute a callback over each item.
333 * @param callable $callback
334 * @return $this
336 public function each(callable $callback)
338 foreach ($this->items as $key => $item) {
339 if ($callback($item, $key) === false) {
340 break;
344 return $this;
348 * Execute a callback over each nested chunk of items.
350 * @param callable $callback
351 * @return static
353 public function eachSpread(callable $callback)
355 return $this->each(function ($chunk, $key) use ($callback) {
356 $chunk[] = $key;
358 return $callback(...$chunk);
363 * Determine if all items in the collection pass the given test.
365 * @param string|callable $key
366 * @param mixed $operator
367 * @param mixed $value
368 * @return bool
370 public function every($key, $operator = null, $value = null)
372 if (func_num_args() == 1) {
373 $callback = $this->valueRetriever($key);
375 foreach ($this->items as $k => $v) {
376 if (! $callback($v, $k)) {
377 return false;
381 return true;
384 return $this->every($this->operatorForWhere(...func_get_args()));
388 * Get all items except for those with the specified keys.
390 * @param \Illuminate\Support\Collection|mixed $keys
391 * @return static
393 public function except($keys)
395 if ($keys instanceof self) {
396 $keys = $keys->all();
397 } elseif (! is_array($keys)) {
398 $keys = func_get_args();
401 return new static(Arr::except($this->items, $keys));
405 * Run a filter over each of the items.
407 * @param callable|null $callback
408 * @return static
410 public function filter(callable $callback = null)
412 if ($callback) {
413 return new static(Arr::where($this->items, $callback));
416 return new static(array_filter($this->items));
420 * Apply the callback if the value is truthy.
422 * @param bool $value
423 * @param callable $callback
424 * @param callable $default
425 * @return mixed
427 public function when($value, callable $callback, callable $default = null)
429 if ($value) {
430 return $callback($this, $value);
431 } elseif ($default) {
432 return $default($this, $value);
435 return $this;
439 * Apply the callback if the value is falsy.
441 * @param bool $value
442 * @param callable $callback
443 * @param callable $default
444 * @return mixed
446 public function unless($value, callable $callback, callable $default = null)
448 return $this->when(! $value, $callback, $default);
452 * Filter items by the given key value pair.
454 * @param string $key
455 * @param mixed $operator
456 * @param mixed $value
457 * @return static
459 public function where($key, $operator, $value = null)
461 return $this->filter($this->operatorForWhere(...func_get_args()));
465 * Get an operator checker callback.
467 * @param string $key
468 * @param string $operator
469 * @param mixed $value
470 * @return \Closure
472 protected function operatorForWhere($key, $operator, $value = null)
474 if (func_num_args() == 2) {
475 $value = $operator;
477 $operator = '=';
480 return function ($item) use ($key, $operator, $value) {
481 $retrieved = data_get($item, $key);
483 $strings = array_filter([$retrieved, $value], function ($value) {
484 return is_string($value) || (is_object($value) && method_exists($value, '__toString'));
487 if (count($strings) < 2 && count(array_filter([$retrieved, $value], 'is_object')) == 1) {
488 return in_array($operator, ['!=', '<>', '!==']);
491 switch ($operator) {
492 default:
493 case '=':
494 case '==': return $retrieved == $value;
495 case '!=':
496 case '<>': return $retrieved != $value;
497 case '<': return $retrieved < $value;
498 case '>': return $retrieved > $value;
499 case '<=': return $retrieved <= $value;
500 case '>=': return $retrieved >= $value;
501 case '===': return $retrieved === $value;
502 case '!==': return $retrieved !== $value;
508 * Filter items by the given key value pair using strict comparison.
510 * @param string $key
511 * @param mixed $value
512 * @return static
514 public function whereStrict($key, $value)
516 return $this->where($key, '===', $value);
520 * Filter items by the given key value pair.
522 * @param string $key
523 * @param mixed $values
524 * @param bool $strict
525 * @return static
527 public function whereIn($key, $values, $strict = false)
529 $values = $this->getArrayableItems($values);
531 return $this->filter(function ($item) use ($key, $values, $strict) {
532 return in_array(data_get($item, $key), $values, $strict);
537 * Filter items by the given key value pair using strict comparison.
539 * @param string $key
540 * @param mixed $values
541 * @return static
543 public function whereInStrict($key, $values)
545 return $this->whereIn($key, $values, true);
549 * Filter items by the given key value pair.
551 * @param string $key
552 * @param mixed $values
553 * @param bool $strict
554 * @return static
556 public function whereNotIn($key, $values, $strict = false)
558 $values = $this->getArrayableItems($values);
560 return $this->reject(function ($item) use ($key, $values, $strict) {
561 return in_array(data_get($item, $key), $values, $strict);
566 * Filter items by the given key value pair using strict comparison.
568 * @param string $key
569 * @param mixed $values
570 * @return static
572 public function whereNotInStrict($key, $values)
574 return $this->whereNotIn($key, $values, true);
578 * Get the first item from the collection.
580 * @param callable|null $callback
581 * @param mixed $default
582 * @return mixed
584 public function first(callable $callback = null, $default = null)
586 return Arr::first($this->items, $callback, $default);
590 * Get the first item by the given key value pair.
592 * @param string $key
593 * @param mixed $operator
594 * @param mixed $value
595 * @return static
597 public function firstWhere($key, $operator, $value = null)
599 return $this->first($this->operatorForWhere(...func_get_args()));
603 * Get a flattened array of the items in the collection.
605 * @param int $depth
606 * @return static
608 public function flatten($depth = INF)
610 return new static(Arr::flatten($this->items, $depth));
614 * Flip the items in the collection.
616 * @return static
618 public function flip()
620 return new static(array_flip($this->items));
624 * Remove an item from the collection by key.
626 * @param string|array $keys
627 * @return $this
629 public function forget($keys)
631 foreach ((array) $keys as $key) {
632 $this->offsetUnset($key);
635 return $this;
639 * Get an item from the collection by key.
641 * @param mixed $key
642 * @param mixed $default
643 * @return mixed
645 public function get($key, $default = null)
647 if ($this->offsetExists($key)) {
648 return $this->items[$key];
651 return value($default);
655 * Group an associative array by a field or using a callback.
657 * @param callable|string $groupBy
658 * @param bool $preserveKeys
659 * @return static
661 public function groupBy($groupBy, $preserveKeys = false)
663 if (is_array($groupBy)) {
664 $nextGroups = $groupBy;
666 $groupBy = array_shift($nextGroups);
669 $groupBy = $this->valueRetriever($groupBy);
671 $results = [];
673 foreach ($this->items as $key => $value) {
674 $groupKeys = $groupBy($value, $key);
676 if (! is_array($groupKeys)) {
677 $groupKeys = [$groupKeys];
680 foreach ($groupKeys as $groupKey) {
681 $groupKey = is_bool($groupKey) ? (int) $groupKey : $groupKey;
683 if (! array_key_exists($groupKey, $results)) {
684 $results[$groupKey] = new static;
687 $results[$groupKey]->offsetSet($preserveKeys ? $key : null, $value);
691 $result = new static($results);
693 if (! empty($nextGroups)) {
694 return $result->map->groupBy($nextGroups, $preserveKeys);
697 return $result;
701 * Key an associative array by a field or using a callback.
703 * @param callable|string $keyBy
704 * @return static
706 public function keyBy($keyBy)
708 $keyBy = $this->valueRetriever($keyBy);
710 $results = [];
712 foreach ($this->items as $key => $item) {
713 $resolvedKey = $keyBy($item, $key);
715 if (is_object($resolvedKey)) {
716 $resolvedKey = (string) $resolvedKey;
719 $results[$resolvedKey] = $item;
722 return new static($results);
726 * Determine if an item exists in the collection by key.
728 * @param mixed $key
729 * @return bool
731 public function has($key)
733 $keys = is_array($key) ? $key : func_get_args();
735 foreach ($keys as $value) {
736 if (! $this->offsetExists($value)) {
737 return false;
741 return true;
745 * Concatenate values of a given key as a string.
747 * @param string $value
748 * @param string $glue
749 * @return string
751 public function implode($value, $glue = null)
753 $first = $this->first();
755 if (is_array($first) || is_object($first)) {
756 return implode($glue, $this->pluck($value)->all());
759 return implode($value, $this->items);
763 * Intersect the collection with the given items.
765 * @param mixed $items
766 * @return static
768 public function intersect($items)
770 return new static(array_intersect($this->items, $this->getArrayableItems($items)));
774 * Intersect the collection with the given items by key.
776 * @param mixed $items
777 * @return static
779 public function intersectByKeys($items)
781 return new static(array_intersect_key(
782 $this->items, $this->getArrayableItems($items)
787 * Determine if the collection is empty or not.
789 * @return bool
791 public function isEmpty()
793 return empty($this->items);
797 * Determine if the collection is not empty.
799 * @return bool
801 public function isNotEmpty()
803 return ! $this->isEmpty();
807 * Determine if the given value is callable, but not a string.
809 * @param mixed $value
810 * @return bool
812 protected function useAsCallable($value)
814 return ! is_string($value) && is_callable($value);
818 * Get the keys of the collection items.
820 * @return static
822 public function keys()
824 return new static(array_keys($this->items));
828 * Get the last item from the collection.
830 * @param callable|null $callback
831 * @param mixed $default
832 * @return mixed
834 public function last(callable $callback = null, $default = null)
836 return Arr::last($this->items, $callback, $default);
840 * Get the values of a given key.
842 * @param string|array $value
843 * @param string|null $key
844 * @return static
846 public function pluck($value, $key = null)
848 return new static(Arr::pluck($this->items, $value, $key));
852 * Run a map over each of the items.
854 * @param callable $callback
855 * @return static
857 public function map(callable $callback)
859 $keys = array_keys($this->items);
861 $items = array_map($callback, $this->items, $keys);
863 return new static(array_combine($keys, $items));
867 * Run a map over each nested chunk of items.
869 * @param callable $callback
870 * @return static
872 public function mapSpread(callable $callback)
874 return $this->map(function ($chunk, $key) use ($callback) {
875 $chunk[] = $key;
877 return $callback(...$chunk);
882 * Run a dictionary map over the items.
884 * The callback should return an associative array with a single key/value pair.
886 * @param callable $callback
887 * @return static
889 public function mapToDictionary(callable $callback)
891 $dictionary = $this->map($callback)->reduce(function ($groups, $pair) {
892 $groups[key($pair)][] = reset($pair);
894 return $groups;
895 }, []);
897 return new static($dictionary);
901 * Run a grouping map over the items.
903 * The callback should return an associative array with a single key/value pair.
905 * @param callable $callback
906 * @return static
908 public function mapToGroups(callable $callback)
910 $groups = $this->mapToDictionary($callback);
912 return $groups->map([$this, 'make']);
916 * Run an associative map over each of the items.
918 * The callback should return an associative array with a single key/value pair.
920 * @param callable $callback
921 * @return static
923 public function mapWithKeys(callable $callback)
925 $result = [];
927 foreach ($this->items as $key => $value) {
928 $assoc = $callback($value, $key);
930 foreach ($assoc as $mapKey => $mapValue) {
931 $result[$mapKey] = $mapValue;
935 return new static($result);
939 * Map a collection and flatten the result by a single level.
941 * @param callable $callback
942 * @return static
944 public function flatMap(callable $callback)
946 return $this->map($callback)->collapse();
950 * Map the values into a new class.
952 * @param string $class
953 * @return static
955 public function mapInto($class)
957 return $this->map(function ($value, $key) use ($class) {
958 return new $class($value, $key);
963 * Get the max value of a given key.
965 * @param callable|string|null $callback
966 * @return mixed
968 public function max($callback = null)
970 $callback = $this->valueRetriever($callback);
972 return $this->filter(function ($value) {
973 return ! is_null($value);
974 })->reduce(function ($result, $item) use ($callback) {
975 $value = $callback($item);
977 return is_null($result) || $value > $result ? $value : $result;
982 * Merge the collection with the given items.
984 * @param mixed $items
985 * @return static
987 public function merge($items)
989 return new static(array_merge($this->items, $this->getArrayableItems($items)));
993 * Create a collection by using this collection for keys and another for its values.
995 * @param mixed $values
996 * @return static
998 public function combine($values)
1000 return new static(array_combine($this->all(), $this->getArrayableItems($values)));
1004 * Union the collection with the given items.
1006 * @param mixed $items
1007 * @return static
1009 public function union($items)
1011 return new static($this->items + $this->getArrayableItems($items));
1015 * Get the min value of a given key.
1017 * @param callable|string|null $callback
1018 * @return mixed
1020 public function min($callback = null)
1022 $callback = $this->valueRetriever($callback);
1024 return $this->filter(function ($value) {
1025 return ! is_null($value);
1026 })->reduce(function ($result, $item) use ($callback) {
1027 $value = $callback($item);
1029 return is_null($result) || $value < $result ? $value : $result;
1034 * Create a new collection consisting of every n-th element.
1036 * @param int $step
1037 * @param int $offset
1038 * @return static
1040 public function nth($step, $offset = 0)
1042 $new = [];
1044 $position = 0;
1046 foreach ($this->items as $item) {
1047 if ($position % $step === $offset) {
1048 $new[] = $item;
1051 $position++;
1054 return new static($new);
1058 * Get the items with the specified keys.
1060 * @param mixed $keys
1061 * @return static
1063 public function only($keys)
1065 if (is_null($keys)) {
1066 return new static($this->items);
1069 if ($keys instanceof self) {
1070 $keys = $keys->all();
1073 $keys = is_array($keys) ? $keys : func_get_args();
1075 return new static(Arr::only($this->items, $keys));
1079 * "Paginate" the collection by slicing it into a smaller collection.
1081 * @param int $page
1082 * @param int $perPage
1083 * @return static
1085 public function forPage($page, $perPage)
1087 $offset = max(0, ($page - 1) * $perPage);
1089 return $this->slice($offset, $perPage);
1093 * Partition the collection into two arrays using the given callback or key.
1095 * @param callable|string $callback
1096 * @return static
1098 public function partition($callback)
1100 $partitions = [new static, new static];
1102 $callback = $this->valueRetriever($callback);
1104 foreach ($this->items as $key => $item) {
1105 $partitions[(int) ! $callback($item, $key)][$key] = $item;
1108 return new static($partitions);
1112 * Pass the collection to the given callback and return the result.
1114 * @param callable $callback
1115 * @return mixed
1117 public function pipe(callable $callback)
1119 return $callback($this);
1123 * Get and remove the last item from the collection.
1125 * @return mixed
1127 public function pop()
1129 return array_pop($this->items);
1133 * Push an item onto the beginning of the collection.
1135 * @param mixed $value
1136 * @param mixed $key
1137 * @return $this
1139 public function prepend($value, $key = null)
1141 $this->items = Arr::prepend($this->items, $value, $key);
1143 return $this;
1147 * Push an item onto the end of the collection.
1149 * @param mixed $value
1150 * @return $this
1152 public function push($value)
1154 $this->offsetSet(null, $value);
1156 return $this;
1160 * Push all of the given items onto the collection.
1162 * @param \Traversable $source
1163 * @return $this
1165 public function concat($source)
1167 $result = new static($this);
1169 foreach ($source as $item) {
1170 $result->push($item);
1173 return $result;
1177 * Get and remove an item from the collection.
1179 * @param mixed $key
1180 * @param mixed $default
1181 * @return mixed
1183 public function pull($key, $default = null)
1185 return Arr::pull($this->items, $key, $default);
1189 * Put an item in the collection by key.
1191 * @param mixed $key
1192 * @param mixed $value
1193 * @return $this
1195 public function put($key, $value)
1197 $this->offsetSet($key, $value);
1199 return $this;
1203 * Get one or a specified number of items randomly from the collection.
1205 * @param int|null $number
1206 * @return mixed
1208 * @throws \InvalidArgumentException
1210 public function random($number = null)
1212 if (is_null($number)) {
1213 return Arr::random($this->items);
1216 return new static(Arr::random($this->items, $number));
1220 * Reduce the collection to a single value.
1222 * @param callable $callback
1223 * @param mixed $initial
1224 * @return mixed
1226 public function reduce(callable $callback, $initial = null)
1228 return array_reduce($this->items, $callback, $initial);
1232 * Create a collection of all elements that do not pass a given truth test.
1234 * @param callable|mixed $callback
1235 * @return static
1237 public function reject($callback)
1239 if ($this->useAsCallable($callback)) {
1240 return $this->filter(function ($value, $key) use ($callback) {
1241 return ! $callback($value, $key);
1245 return $this->filter(function ($item) use ($callback) {
1246 return $item != $callback;
1251 * Reverse items order.
1253 * @return static
1255 public function reverse()
1257 return new static(array_reverse($this->items, true));
1261 * Search the collection for a given value and return the corresponding key if successful.
1263 * @param mixed $value
1264 * @param bool $strict
1265 * @return mixed
1267 public function search($value, $strict = false)
1269 if (! $this->useAsCallable($value)) {
1270 return array_search($value, $this->items, $strict);
1273 foreach ($this->items as $key => $item) {
1274 if (call_user_func($value, $item, $key)) {
1275 return $key;
1279 return false;
1283 * Get and remove the first item from the collection.
1285 * @return mixed
1287 public function shift()
1289 return array_shift($this->items);
1293 * Shuffle the items in the collection.
1295 * @param int $seed
1296 * @return static
1298 public function shuffle($seed = null)
1300 $items = $this->items;
1302 if (is_null($seed)) {
1303 shuffle($items);
1304 } else {
1305 srand($seed);
1307 usort($items, function () {
1308 return rand(-1, 1);
1312 return new static($items);
1316 * Slice the underlying collection array.
1318 * @param int $offset
1319 * @param int $length
1320 * @return static
1322 public function slice($offset, $length = null)
1324 return new static(array_slice($this->items, $offset, $length, true));
1328 * Split a collection into a certain number of groups.
1330 * @param int $numberOfGroups
1331 * @return static
1333 public function split($numberOfGroups)
1335 if ($this->isEmpty()) {
1336 return new static;
1339 $groupSize = ceil($this->count() / $numberOfGroups);
1341 return $this->chunk($groupSize);
1345 * Chunk the underlying collection array.
1347 * @param int $size
1348 * @return static
1350 public function chunk($size)
1352 if ($size <= 0) {
1353 return new static;
1356 $chunks = [];
1358 foreach (array_chunk($this->items, $size, true) as $chunk) {
1359 $chunks[] = new static($chunk);
1362 return new static($chunks);
1366 * Sort through each item with a callback.
1368 * @param callable|null $callback
1369 * @return static
1371 public function sort(callable $callback = null)
1373 $items = $this->items;
1375 $callback
1376 ? uasort($items, $callback)
1377 : asort($items);
1379 return new static($items);
1383 * Sort the collection using the given callback.
1385 * @param callable|string $callback
1386 * @param int $options
1387 * @param bool $descending
1388 * @return static
1390 public function sortBy($callback, $options = SORT_REGULAR, $descending = false)
1392 $results = [];
1394 $callback = $this->valueRetriever($callback);
1396 // First we will loop through the items and get the comparator from a callback
1397 // function which we were given. Then, we will sort the returned values and
1398 // and grab the corresponding values for the sorted keys from this array.
1399 foreach ($this->items as $key => $value) {
1400 $results[$key] = $callback($value, $key);
1403 $descending ? arsort($results, $options)
1404 : asort($results, $options);
1406 // Once we have sorted all of the keys in the array, we will loop through them
1407 // and grab the corresponding model so we can set the underlying items list
1408 // to the sorted version. Then we'll just return the collection instance.
1409 foreach (array_keys($results) as $key) {
1410 $results[$key] = $this->items[$key];
1413 return new static($results);
1417 * Sort the collection in descending order using the given callback.
1419 * @param callable|string $callback
1420 * @param int $options
1421 * @return static
1423 public function sortByDesc($callback, $options = SORT_REGULAR)
1425 return $this->sortBy($callback, $options, true);
1429 * Splice a portion of the underlying collection array.
1431 * @param int $offset
1432 * @param int|null $length
1433 * @param mixed $replacement
1434 * @return static
1436 public function splice($offset, $length = null, $replacement = [])
1438 if (func_num_args() == 1) {
1439 return new static(array_splice($this->items, $offset));
1442 return new static(array_splice($this->items, $offset, $length, $replacement));
1446 * Get the sum of the given values.
1448 * @param callable|string|null $callback
1449 * @return mixed
1451 public function sum($callback = null)
1453 if (is_null($callback)) {
1454 return array_sum($this->items);
1457 $callback = $this->valueRetriever($callback);
1459 return $this->reduce(function ($result, $item) use ($callback) {
1460 return $result + $callback($item);
1461 }, 0);
1465 * Take the first or last {$limit} items.
1467 * @param int $limit
1468 * @return static
1470 public function take($limit)
1472 if ($limit < 0) {
1473 return $this->slice($limit, abs($limit));
1476 return $this->slice(0, $limit);
1480 * Pass the collection to the given callback and then return it.
1482 * @param callable $callback
1483 * @return $this
1485 public function tap(callable $callback)
1487 $callback(new static($this->items));
1489 return $this;
1493 * Transform each item in the collection using a callback.
1495 * @param callable $callback
1496 * @return $this
1498 public function transform(callable $callback)
1500 $this->items = $this->map($callback)->all();
1502 return $this;
1506 * Return only unique items from the collection array.
1508 * @param string|callable|null $key
1509 * @param bool $strict
1510 * @return static
1512 public function unique($key = null, $strict = false)
1514 if (is_null($key)) {
1515 return new static(array_unique($this->items, SORT_REGULAR));
1518 $callback = $this->valueRetriever($key);
1520 $exists = [];
1522 return $this->reject(function ($item, $key) use ($callback, $strict, &$exists) {
1523 if (in_array($id = $callback($item, $key), $exists, $strict)) {
1524 return true;
1527 $exists[] = $id;
1532 * Return only unique items from the collection array using strict comparison.
1534 * @param string|callable|null $key
1535 * @return static
1537 public function uniqueStrict($key = null)
1539 return $this->unique($key, true);
1543 * Reset the keys on the underlying array.
1545 * @return static
1547 public function values()
1549 return new static(array_values($this->items));
1553 * Get a value retrieving callback.
1555 * @param string $value
1556 * @return callable
1558 protected function valueRetriever($value)
1560 if ($this->useAsCallable($value)) {
1561 return $value;
1564 return function ($item) use ($value) {
1565 return data_get($item, $value);
1570 * Zip the collection together with one or more arrays.
1572 * e.g. new Collection([1, 2, 3])->zip([4, 5, 6]);
1573 * => [[1, 4], [2, 5], [3, 6]]
1575 * @param mixed ...$items
1576 * @return static
1578 public function zip($items)
1580 $arrayableItems = array_map(function ($items) {
1581 return $this->getArrayableItems($items);
1582 }, func_get_args());
1584 $params = array_merge([function () {
1585 return new static(func_get_args());
1586 }, $this->items], $arrayableItems);
1588 return new static(call_user_func_array('array_map', $params));
1592 * Pad collection to the specified length with a value.
1594 * @param int $size
1595 * @param mixed $value
1596 * @return static
1598 public function pad($size, $value)
1600 return new static(array_pad($this->items, $size, $value));
1604 * Get the collection of items as a plain array.
1606 * @return array
1608 public function toArray()
1610 return array_map(function ($value) {
1611 return $value instanceof Arrayable ? $value->toArray() : $value;
1612 }, $this->items);
1616 * Convert the object into something JSON serializable.
1618 * @return array
1620 public function jsonSerialize()
1622 return array_map(function ($value) {
1623 if ($value instanceof JsonSerializable) {
1624 return $value->jsonSerialize();
1625 } elseif ($value instanceof Jsonable) {
1626 return json_decode($value->toJson(), true);
1627 } elseif ($value instanceof Arrayable) {
1628 return $value->toArray();
1631 return $value;
1632 }, $this->items);
1636 * Get the collection of items as JSON.
1638 * @param int $options
1639 * @return string
1641 public function toJson($options = 0)
1643 return json_encode($this->jsonSerialize(), $options);
1647 * Get an iterator for the items.
1649 * @return \ArrayIterator
1651 public function getIterator()
1653 return new ArrayIterator($this->items);
1657 * Get a CachingIterator instance.
1659 * @param int $flags
1660 * @return \CachingIterator
1662 public function getCachingIterator($flags = CachingIterator::CALL_TOSTRING)
1664 return new CachingIterator($this->getIterator(), $flags);
1668 * Count the number of items in the collection.
1670 * @return int
1672 public function count()
1674 return count($this->items);
1678 * Get a base Support collection instance from this collection.
1680 * @return \Illuminate\Support\Collection
1682 public function toBase()
1684 return new self($this);
1688 * Determine if an item exists at an offset.
1690 * @param mixed $key
1691 * @return bool
1693 public function offsetExists($key)
1695 return array_key_exists($key, $this->items);
1699 * Get an item at a given offset.
1701 * @param mixed $key
1702 * @return mixed
1704 public function offsetGet($key)
1706 return $this->items[$key];
1710 * Set the item at a given offset.
1712 * @param mixed $key
1713 * @param mixed $value
1714 * @return void
1716 public function offsetSet($key, $value)
1718 if (is_null($key)) {
1719 $this->items[] = $value;
1720 } else {
1721 $this->items[$key] = $value;
1726 * Unset the item at a given offset.
1728 * @param string $key
1729 * @return void
1731 public function offsetUnset($key)
1733 unset($this->items[$key]);
1737 * Convert the collection to its string representation.
1739 * @return string
1741 public function __toString()
1743 return $this->toJson();
1747 * Results array of items from Collection or Arrayable.
1749 * @param mixed $items
1750 * @return array
1752 protected function getArrayableItems($items)
1754 if (is_array($items)) {
1755 return $items;
1756 } elseif ($items instanceof self) {
1757 return $items->all();
1758 } elseif ($items instanceof Arrayable) {
1759 return $items->toArray();
1760 } elseif ($items instanceof Jsonable) {
1761 return json_decode($items->toJson(), true);
1762 } elseif ($items instanceof JsonSerializable) {
1763 return $items->jsonSerialize();
1764 } elseif ($items instanceof Traversable) {
1765 return iterator_to_array($items);
1768 return (array) $items;
1772 * Add a method to the list of proxied methods.
1774 * @param string $method
1775 * @return void
1777 public static function proxy($method)
1779 static::$proxies[] = $method;
1783 * Dynamically access collection proxies.
1785 * @param string $key
1786 * @return mixed
1788 * @throws \Exception
1790 public function __get($key)
1792 if (! in_array($key, static::$proxies)) {
1793 throw new Exception("Property [{$key}] does not exist on this collection instance.");
1796 return new HigherOrderCollectionProxy($this, $key);