/vendor/laravel/framework/src/Illuminate/Support/Collection.php

https://gitlab.com/milton2913/myBlog · PHP · 1342 lines · 610 code · 175 blank · 557 comment · 53 complexity · 0e32bc702de49682eda244b48cae3a53 MD5 · raw file

  1. <?php
  2. namespace Illuminate\Support;
  3. use Countable;
  4. use ArrayAccess;
  5. use Traversable;
  6. use ArrayIterator;
  7. use CachingIterator;
  8. use JsonSerializable;
  9. use IteratorAggregate;
  10. use InvalidArgumentException;
  11. use Illuminate\Support\Traits\Macroable;
  12. use Illuminate\Contracts\Support\Jsonable;
  13. use Illuminate\Contracts\Support\Arrayable;
  14. class Collection implements ArrayAccess, Arrayable, Countable, IteratorAggregate, Jsonable, JsonSerializable
  15. {
  16. use Macroable;
  17. /**
  18. * The items contained in the collection.
  19. *
  20. * @var array
  21. */
  22. protected $items = [];
  23. /**
  24. * Create a new collection.
  25. *
  26. * @param mixed $items
  27. * @return void
  28. */
  29. public function __construct($items = [])
  30. {
  31. $this->items = $this->getArrayableItems($items);
  32. }
  33. /**
  34. * Create a new collection instance if the value isn't one already.
  35. *
  36. * @param mixed $items
  37. * @return static
  38. */
  39. public static function make($items = [])
  40. {
  41. return new static($items);
  42. }
  43. /**
  44. * Get all of the items in the collection.
  45. *
  46. * @return array
  47. */
  48. public function all()
  49. {
  50. return $this->items;
  51. }
  52. /**
  53. * Get the average value of a given key.
  54. *
  55. * @param callable|string|null $callback
  56. * @return mixed
  57. */
  58. public function avg($callback = null)
  59. {
  60. if ($count = $this->count()) {
  61. return $this->sum($callback) / $count;
  62. }
  63. }
  64. /**
  65. * Alias for the "avg" method.
  66. *
  67. * @param callable|string|null $callback
  68. * @return mixed
  69. */
  70. public function average($callback = null)
  71. {
  72. return $this->avg($callback);
  73. }
  74. /**
  75. * Get the median of a given key.
  76. *
  77. * @param null $key
  78. * @return mixed|null
  79. */
  80. public function median($key = null)
  81. {
  82. $count = $this->count();
  83. if ($count == 0) {
  84. return;
  85. }
  86. $values = with(isset($key) ? $this->pluck($key) : $this)
  87. ->sort()->values();
  88. $middle = (int) ($count / 2);
  89. if ($count % 2) {
  90. return $values->get($middle);
  91. }
  92. return (new static([
  93. $values->get($middle - 1), $values->get($middle),
  94. ]))->average();
  95. }
  96. /**
  97. * Get the mode of a given key.
  98. *
  99. * @param null $key
  100. * @return array
  101. */
  102. public function mode($key = null)
  103. {
  104. $count = $this->count();
  105. if ($count == 0) {
  106. return;
  107. }
  108. $collection = isset($key) ? $this->pluck($key) : $this;
  109. $counts = new self;
  110. $collection->each(function ($value) use ($counts) {
  111. $counts[$value] = isset($counts[$value]) ? $counts[$value] + 1 : 1;
  112. });
  113. $sorted = $counts->sort();
  114. $highestValue = $sorted->last();
  115. return $sorted->filter(function ($value) use ($highestValue) {
  116. return $value == $highestValue;
  117. })->sort()->keys()->all();
  118. }
  119. /**
  120. * Collapse the collection of items into a single array.
  121. *
  122. * @return static
  123. */
  124. public function collapse()
  125. {
  126. return new static(Arr::collapse($this->items));
  127. }
  128. /**
  129. * Determine if an item exists in the collection.
  130. *
  131. * @param mixed $key
  132. * @param mixed $value
  133. * @return bool
  134. */
  135. public function contains($key, $value = null)
  136. {
  137. if (func_num_args() == 2) {
  138. return $this->contains(function ($item) use ($key, $value) {
  139. return data_get($item, $key) == $value;
  140. });
  141. }
  142. if ($this->useAsCallable($key)) {
  143. return ! is_null($this->first($key));
  144. }
  145. return in_array($key, $this->items);
  146. }
  147. /**
  148. * Determine if an item exists in the collection using strict comparison.
  149. *
  150. * @param mixed $key
  151. * @param mixed $value
  152. * @return bool
  153. */
  154. public function containsStrict($key, $value = null)
  155. {
  156. if (func_num_args() == 2) {
  157. return $this->contains(function ($item) use ($key, $value) {
  158. return data_get($item, $key) === $value;
  159. });
  160. }
  161. if ($this->useAsCallable($key)) {
  162. return ! is_null($this->first($key));
  163. }
  164. return in_array($key, $this->items, true);
  165. }
  166. /**
  167. * Get the items in the collection that are not present in the given items.
  168. *
  169. * @param mixed $items
  170. * @return static
  171. */
  172. public function diff($items)
  173. {
  174. return new static(array_diff($this->items, $this->getArrayableItems($items)));
  175. }
  176. /**
  177. * Get the items in the collection whose keys are not present in the given items.
  178. *
  179. * @param mixed $items
  180. * @return static
  181. */
  182. public function diffKeys($items)
  183. {
  184. return new static(array_diff_key($this->items, $this->getArrayableItems($items)));
  185. }
  186. /**
  187. * Execute a callback over each item.
  188. *
  189. * @param callable $callback
  190. * @return $this
  191. */
  192. public function each(callable $callback)
  193. {
  194. foreach ($this->items as $key => $item) {
  195. if ($callback($item, $key) === false) {
  196. break;
  197. }
  198. }
  199. return $this;
  200. }
  201. /**
  202. * Create a new collection consisting of every n-th element.
  203. *
  204. * @param int $step
  205. * @param int $offset
  206. * @return static
  207. */
  208. public function every($step, $offset = 0)
  209. {
  210. $new = [];
  211. $position = 0;
  212. foreach ($this->items as $item) {
  213. if ($position % $step === $offset) {
  214. $new[] = $item;
  215. }
  216. $position++;
  217. }
  218. return new static($new);
  219. }
  220. /**
  221. * Get all items except for those with the specified keys.
  222. *
  223. * @param mixed $keys
  224. * @return static
  225. */
  226. public function except($keys)
  227. {
  228. $keys = is_array($keys) ? $keys : func_get_args();
  229. return new static(Arr::except($this->items, $keys));
  230. }
  231. /**
  232. * Run a filter over each of the items.
  233. *
  234. * @param callable|null $callback
  235. * @return static
  236. */
  237. public function filter(callable $callback = null)
  238. {
  239. if ($callback) {
  240. return new static(Arr::where($this->items, $callback));
  241. }
  242. return new static(array_filter($this->items));
  243. }
  244. /**
  245. * Filter items by the given key value pair.
  246. *
  247. * @param string $key
  248. * @param mixed $operator
  249. * @param mixed $value
  250. * @return static
  251. */
  252. public function where($key, $operator, $value = null)
  253. {
  254. if (func_num_args() == 2) {
  255. $value = $operator;
  256. $operator = '=';
  257. }
  258. return $this->filter($this->operatorForWhere($key, $operator, $value));
  259. }
  260. /**
  261. * Get an operator checker callback.
  262. *
  263. * @param string $key
  264. * @param string $operator
  265. * @param mixed $value
  266. * @return \Closure
  267. */
  268. protected function operatorForWhere($key, $operator, $value)
  269. {
  270. return function ($item) use ($key, $operator, $value) {
  271. $retrieved = data_get($item, $key);
  272. switch ($operator) {
  273. default:
  274. case '=':
  275. case '==': return $retrieved == $value;
  276. case '!=':
  277. case '<>': return $retrieved != $value;
  278. case '<': return $retrieved < $value;
  279. case '>': return $retrieved > $value;
  280. case '<=': return $retrieved <= $value;
  281. case '>=': return $retrieved >= $value;
  282. case '===': return $retrieved === $value;
  283. case '!==': return $retrieved !== $value;
  284. }
  285. };
  286. }
  287. /**
  288. * Filter items by the given key value pair using strict comparison.
  289. *
  290. * @param string $key
  291. * @param mixed $value
  292. * @return static
  293. */
  294. public function whereStrict($key, $value)
  295. {
  296. return $this->where($key, '===', $value);
  297. }
  298. /**
  299. * Filter items by the given key value pair.
  300. *
  301. * @param string $key
  302. * @param mixed $values
  303. * @param bool $strict
  304. * @return static
  305. */
  306. public function whereIn($key, $values, $strict = false)
  307. {
  308. $values = $this->getArrayableItems($values);
  309. return $this->filter(function ($item) use ($key, $values, $strict) {
  310. return in_array(data_get($item, $key), $values, $strict);
  311. });
  312. }
  313. /**
  314. * Filter items by the given key value pair using strict comparison.
  315. *
  316. * @param string $key
  317. * @param mixed $values
  318. * @return static
  319. */
  320. public function whereInStrict($key, $values)
  321. {
  322. return $this->whereIn($key, $values, true);
  323. }
  324. /**
  325. * Get the first item from the collection.
  326. *
  327. * @param callable|null $callback
  328. * @param mixed $default
  329. * @return mixed
  330. */
  331. public function first(callable $callback = null, $default = null)
  332. {
  333. return Arr::first($this->items, $callback, $default);
  334. }
  335. /**
  336. * Get a flattened array of the items in the collection.
  337. *
  338. * @param int $depth
  339. * @return static
  340. */
  341. public function flatten($depth = INF)
  342. {
  343. return new static(Arr::flatten($this->items, $depth));
  344. }
  345. /**
  346. * Flip the items in the collection.
  347. *
  348. * @return static
  349. */
  350. public function flip()
  351. {
  352. return new static(array_flip($this->items));
  353. }
  354. /**
  355. * Remove an item from the collection by key.
  356. *
  357. * @param string|array $keys
  358. * @return $this
  359. */
  360. public function forget($keys)
  361. {
  362. foreach ((array) $keys as $key) {
  363. $this->offsetUnset($key);
  364. }
  365. return $this;
  366. }
  367. /**
  368. * Get an item from the collection by key.
  369. *
  370. * @param mixed $key
  371. * @param mixed $default
  372. * @return mixed
  373. */
  374. public function get($key, $default = null)
  375. {
  376. if ($this->offsetExists($key)) {
  377. return $this->items[$key];
  378. }
  379. return value($default);
  380. }
  381. /**
  382. * Group an associative array by a field or using a callback.
  383. *
  384. * @param callable|string $groupBy
  385. * @param bool $preserveKeys
  386. * @return static
  387. */
  388. public function groupBy($groupBy, $preserveKeys = false)
  389. {
  390. $groupBy = $this->valueRetriever($groupBy);
  391. $results = [];
  392. foreach ($this->items as $key => $value) {
  393. $groupKeys = $groupBy($value, $key);
  394. if (! is_array($groupKeys)) {
  395. $groupKeys = [$groupKeys];
  396. }
  397. foreach ($groupKeys as $groupKey) {
  398. if (! array_key_exists($groupKey, $results)) {
  399. $results[$groupKey] = new static;
  400. }
  401. $results[$groupKey]->offsetSet($preserveKeys ? $key : null, $value);
  402. }
  403. }
  404. return new static($results);
  405. }
  406. /**
  407. * Key an associative array by a field or using a callback.
  408. *
  409. * @param callable|string $keyBy
  410. * @return static
  411. */
  412. public function keyBy($keyBy)
  413. {
  414. $keyBy = $this->valueRetriever($keyBy);
  415. $results = [];
  416. foreach ($this->items as $key => $item) {
  417. $results[$keyBy($item, $key)] = $item;
  418. }
  419. return new static($results);
  420. }
  421. /**
  422. * Determine if an item exists in the collection by key.
  423. *
  424. * @param mixed $key
  425. * @return bool
  426. */
  427. public function has($key)
  428. {
  429. return $this->offsetExists($key);
  430. }
  431. /**
  432. * Concatenate values of a given key as a string.
  433. *
  434. * @param string $value
  435. * @param string $glue
  436. * @return string
  437. */
  438. public function implode($value, $glue = null)
  439. {
  440. $first = $this->first();
  441. if (is_array($first) || is_object($first)) {
  442. return implode($glue, $this->pluck($value)->all());
  443. }
  444. return implode($value, $this->items);
  445. }
  446. /**
  447. * Intersect the collection with the given items.
  448. *
  449. * @param mixed $items
  450. * @return static
  451. */
  452. public function intersect($items)
  453. {
  454. return new static(array_intersect($this->items, $this->getArrayableItems($items)));
  455. }
  456. /**
  457. * Determine if the collection is empty or not.
  458. *
  459. * @return bool
  460. */
  461. public function isEmpty()
  462. {
  463. return empty($this->items);
  464. }
  465. /**
  466. * Determine if the given value is callable, but not a string.
  467. *
  468. * @param mixed $value
  469. * @return bool
  470. */
  471. protected function useAsCallable($value)
  472. {
  473. return ! is_string($value) && is_callable($value);
  474. }
  475. /**
  476. * Get the keys of the collection items.
  477. *
  478. * @return static
  479. */
  480. public function keys()
  481. {
  482. return new static(array_keys($this->items));
  483. }
  484. /**
  485. * Get the last item from the collection.
  486. *
  487. * @param callable|null $callback
  488. * @param mixed $default
  489. * @return mixed
  490. */
  491. public function last(callable $callback = null, $default = null)
  492. {
  493. return Arr::last($this->items, $callback, $default);
  494. }
  495. /**
  496. * Get the values of a given key.
  497. *
  498. * @param string $value
  499. * @param string|null $key
  500. * @return static
  501. */
  502. public function pluck($value, $key = null)
  503. {
  504. return new static(Arr::pluck($this->items, $value, $key));
  505. }
  506. /**
  507. * Run a map over each of the items.
  508. *
  509. * @param callable $callback
  510. * @return static
  511. */
  512. public function map(callable $callback)
  513. {
  514. $keys = array_keys($this->items);
  515. $items = array_map($callback, $this->items, $keys);
  516. return new static(array_combine($keys, $items));
  517. }
  518. /**
  519. * Run an associative map over each of the items.
  520. *
  521. * The callback should return an associative array with a single key/value pair.
  522. *
  523. * @param callable $callback
  524. * @return static
  525. */
  526. public function mapWithKeys(callable $callback)
  527. {
  528. return $this->flatMap($callback);
  529. }
  530. /**
  531. * Map a collection and flatten the result by a single level.
  532. *
  533. * @param callable $callback
  534. * @return static
  535. */
  536. public function flatMap(callable $callback)
  537. {
  538. return $this->map($callback)->collapse();
  539. }
  540. /**
  541. * Get the max value of a given key.
  542. *
  543. * @param callable|string|null $callback
  544. * @return mixed
  545. */
  546. public function max($callback = null)
  547. {
  548. $callback = $this->valueRetriever($callback);
  549. return $this->reduce(function ($result, $item) use ($callback) {
  550. $value = $callback($item);
  551. return is_null($result) || $value > $result ? $value : $result;
  552. });
  553. }
  554. /**
  555. * Merge the collection with the given items.
  556. *
  557. * @param mixed $items
  558. * @return static
  559. */
  560. public function merge($items)
  561. {
  562. return new static(array_merge($this->items, $this->getArrayableItems($items)));
  563. }
  564. /**
  565. * Create a collection by using this collection for keys and another for its values.
  566. *
  567. * @param mixed $values
  568. * @return static
  569. */
  570. public function combine($values)
  571. {
  572. return new static(array_combine($this->all(), $this->getArrayableItems($values)));
  573. }
  574. /**
  575. * Union the collection with the given items.
  576. *
  577. * @param mixed $items
  578. * @return static
  579. */
  580. public function union($items)
  581. {
  582. return new static($this->items + $this->getArrayableItems($items));
  583. }
  584. /**
  585. * Get the min value of a given key.
  586. *
  587. * @param callable|string|null $callback
  588. * @return mixed
  589. */
  590. public function min($callback = null)
  591. {
  592. $callback = $this->valueRetriever($callback);
  593. return $this->reduce(function ($result, $item) use ($callback) {
  594. $value = $callback($item);
  595. return is_null($result) || $value < $result ? $value : $result;
  596. });
  597. }
  598. /**
  599. * Get the items with the specified keys.
  600. *
  601. * @param mixed $keys
  602. * @return static
  603. */
  604. public function only($keys)
  605. {
  606. if (is_null($keys)) {
  607. return new static($this->items);
  608. }
  609. $keys = is_array($keys) ? $keys : func_get_args();
  610. return new static(Arr::only($this->items, $keys));
  611. }
  612. /**
  613. * "Paginate" the collection by slicing it into a smaller collection.
  614. *
  615. * @param int $page
  616. * @param int $perPage
  617. * @return static
  618. */
  619. public function forPage($page, $perPage)
  620. {
  621. return $this->slice(($page - 1) * $perPage, $perPage);
  622. }
  623. /**
  624. * Pass the collection to the given callback and return the result.
  625. *
  626. * @param callable $callback
  627. * @return mixed
  628. */
  629. public function pipe(callable $callback)
  630. {
  631. return $callback($this);
  632. }
  633. /**
  634. * Get and remove the last item from the collection.
  635. *
  636. * @return mixed
  637. */
  638. public function pop()
  639. {
  640. return array_pop($this->items);
  641. }
  642. /**
  643. * Push an item onto the beginning of the collection.
  644. *
  645. * @param mixed $value
  646. * @param mixed $key
  647. * @return $this
  648. */
  649. public function prepend($value, $key = null)
  650. {
  651. $this->items = Arr::prepend($this->items, $value, $key);
  652. return $this;
  653. }
  654. /**
  655. * Push an item onto the end of the collection.
  656. *
  657. * @param mixed $value
  658. * @return $this
  659. */
  660. public function push($value)
  661. {
  662. $this->offsetSet(null, $value);
  663. return $this;
  664. }
  665. /**
  666. * Get and remove an item from the collection.
  667. *
  668. * @param mixed $key
  669. * @param mixed $default
  670. * @return mixed
  671. */
  672. public function pull($key, $default = null)
  673. {
  674. return Arr::pull($this->items, $key, $default);
  675. }
  676. /**
  677. * Put an item in the collection by key.
  678. *
  679. * @param mixed $key
  680. * @param mixed $value
  681. * @return $this
  682. */
  683. public function put($key, $value)
  684. {
  685. $this->offsetSet($key, $value);
  686. return $this;
  687. }
  688. /**
  689. * Get one or more items randomly from the collection.
  690. *
  691. * @param int $amount
  692. * @return mixed
  693. *
  694. * @throws \InvalidArgumentException
  695. */
  696. public function random($amount = 1)
  697. {
  698. if ($amount > ($count = $this->count())) {
  699. throw new InvalidArgumentException("You requested {$amount} items, but there are only {$count} items in the collection");
  700. }
  701. $keys = array_rand($this->items, $amount);
  702. if ($amount == 1) {
  703. return $this->items[$keys];
  704. }
  705. return new static(array_intersect_key($this->items, array_flip($keys)));
  706. }
  707. /**
  708. * Reduce the collection to a single value.
  709. *
  710. * @param callable $callback
  711. * @param mixed $initial
  712. * @return mixed
  713. */
  714. public function reduce(callable $callback, $initial = null)
  715. {
  716. return array_reduce($this->items, $callback, $initial);
  717. }
  718. /**
  719. * Create a collection of all elements that do not pass a given truth test.
  720. *
  721. * @param callable|mixed $callback
  722. * @return static
  723. */
  724. public function reject($callback)
  725. {
  726. if ($this->useAsCallable($callback)) {
  727. return $this->filter(function ($value, $key) use ($callback) {
  728. return ! $callback($value, $key);
  729. });
  730. }
  731. return $this->filter(function ($item) use ($callback) {
  732. return $item != $callback;
  733. });
  734. }
  735. /**
  736. * Reverse items order.
  737. *
  738. * @return static
  739. */
  740. public function reverse()
  741. {
  742. return new static(array_reverse($this->items, true));
  743. }
  744. /**
  745. * Search the collection for a given value and return the corresponding key if successful.
  746. *
  747. * @param mixed $value
  748. * @param bool $strict
  749. * @return mixed
  750. */
  751. public function search($value, $strict = false)
  752. {
  753. if (! $this->useAsCallable($value)) {
  754. return array_search($value, $this->items, $strict);
  755. }
  756. foreach ($this->items as $key => $item) {
  757. if (call_user_func($value, $item, $key)) {
  758. return $key;
  759. }
  760. }
  761. return false;
  762. }
  763. /**
  764. * Get and remove the first item from the collection.
  765. *
  766. * @return mixed
  767. */
  768. public function shift()
  769. {
  770. return array_shift($this->items);
  771. }
  772. /**
  773. * Shuffle the items in the collection.
  774. *
  775. * @param int $seed
  776. * @return static
  777. */
  778. public function shuffle($seed = null)
  779. {
  780. $items = $this->items;
  781. if (is_null($seed)) {
  782. shuffle($items);
  783. } else {
  784. srand($seed);
  785. usort($items, function () {
  786. return rand(-1, 1);
  787. });
  788. }
  789. return new static($items);
  790. }
  791. /**
  792. * Slice the underlying collection array.
  793. *
  794. * @param int $offset
  795. * @param int $length
  796. * @return static
  797. */
  798. public function slice($offset, $length = null)
  799. {
  800. return new static(array_slice($this->items, $offset, $length, true));
  801. }
  802. /**
  803. * Split a collection into a certain number of groups.
  804. *
  805. * @param int $numberOfGroups
  806. * @return static
  807. */
  808. public function split($numberOfGroups)
  809. {
  810. if ($this->isEmpty()) {
  811. return new static;
  812. }
  813. $groupSize = ceil($this->count() / $numberOfGroups);
  814. return $this->chunk($groupSize);
  815. }
  816. /**
  817. * Chunk the underlying collection array.
  818. *
  819. * @param int $size
  820. * @return static
  821. */
  822. public function chunk($size)
  823. {
  824. $chunks = [];
  825. foreach (array_chunk($this->items, $size, true) as $chunk) {
  826. $chunks[] = new static($chunk);
  827. }
  828. return new static($chunks);
  829. }
  830. /**
  831. * Sort through each item with a callback.
  832. *
  833. * @param callable|null $callback
  834. * @return static
  835. */
  836. public function sort(callable $callback = null)
  837. {
  838. $items = $this->items;
  839. $callback
  840. ? uasort($items, $callback)
  841. : asort($items);
  842. return new static($items);
  843. }
  844. /**
  845. * Sort the collection using the given callback.
  846. *
  847. * @param callable|string $callback
  848. * @param int $options
  849. * @param bool $descending
  850. * @return static
  851. */
  852. public function sortBy($callback, $options = SORT_REGULAR, $descending = false)
  853. {
  854. $results = [];
  855. $callback = $this->valueRetriever($callback);
  856. // First we will loop through the items and get the comparator from a callback
  857. // function which we were given. Then, we will sort the returned values and
  858. // and grab the corresponding values for the sorted keys from this array.
  859. foreach ($this->items as $key => $value) {
  860. $results[$key] = $callback($value, $key);
  861. }
  862. $descending ? arsort($results, $options)
  863. : asort($results, $options);
  864. // Once we have sorted all of the keys in the array, we will loop through them
  865. // and grab the corresponding model so we can set the underlying items list
  866. // to the sorted version. Then we'll just return the collection instance.
  867. foreach (array_keys($results) as $key) {
  868. $results[$key] = $this->items[$key];
  869. }
  870. return new static($results);
  871. }
  872. /**
  873. * Sort the collection in descending order using the given callback.
  874. *
  875. * @param callable|string $callback
  876. * @param int $options
  877. * @return static
  878. */
  879. public function sortByDesc($callback, $options = SORT_REGULAR)
  880. {
  881. return $this->sortBy($callback, $options, true);
  882. }
  883. /**
  884. * Splice a portion of the underlying collection array.
  885. *
  886. * @param int $offset
  887. * @param int|null $length
  888. * @param mixed $replacement
  889. * @return static
  890. */
  891. public function splice($offset, $length = null, $replacement = [])
  892. {
  893. if (func_num_args() == 1) {
  894. return new static(array_splice($this->items, $offset));
  895. }
  896. return new static(array_splice($this->items, $offset, $length, $replacement));
  897. }
  898. /**
  899. * Get the sum of the given values.
  900. *
  901. * @param callable|string|null $callback
  902. * @return mixed
  903. */
  904. public function sum($callback = null)
  905. {
  906. if (is_null($callback)) {
  907. return array_sum($this->items);
  908. }
  909. $callback = $this->valueRetriever($callback);
  910. return $this->reduce(function ($result, $item) use ($callback) {
  911. return $result + $callback($item);
  912. }, 0);
  913. }
  914. /**
  915. * Take the first or last {$limit} items.
  916. *
  917. * @param int $limit
  918. * @return static
  919. */
  920. public function take($limit)
  921. {
  922. if ($limit < 0) {
  923. return $this->slice($limit, abs($limit));
  924. }
  925. return $this->slice(0, $limit);
  926. }
  927. /**
  928. * Transform each item in the collection using a callback.
  929. *
  930. * @param callable $callback
  931. * @return $this
  932. */
  933. public function transform(callable $callback)
  934. {
  935. $this->items = $this->map($callback)->all();
  936. return $this;
  937. }
  938. /**
  939. * Return only unique items from the collection array.
  940. *
  941. * @param string|callable|null $key
  942. * @param bool $strict
  943. *
  944. * @return static
  945. */
  946. public function unique($key = null, $strict = false)
  947. {
  948. if (is_null($key)) {
  949. return new static(array_unique($this->items, SORT_REGULAR));
  950. }
  951. $key = $this->valueRetriever($key);
  952. $exists = [];
  953. return $this->reject(function ($item) use ($key, $strict, &$exists) {
  954. if (in_array($id = $key($item), $exists, $strict)) {
  955. return true;
  956. }
  957. $exists[] = $id;
  958. });
  959. }
  960. /**
  961. * Return only unique items from the collection array using strict comparison.
  962. *
  963. * @param string|callable|null $key
  964. * @return static
  965. */
  966. public function uniqueStrict($key = null)
  967. {
  968. return $this->unique($key, true);
  969. }
  970. /**
  971. * Reset the keys on the underlying array.
  972. *
  973. * @return static
  974. */
  975. public function values()
  976. {
  977. return new static(array_values($this->items));
  978. }
  979. /**
  980. * Get a value retrieving callback.
  981. *
  982. * @param string $value
  983. * @return callable
  984. */
  985. protected function valueRetriever($value)
  986. {
  987. if ($this->useAsCallable($value)) {
  988. return $value;
  989. }
  990. return function ($item) use ($value) {
  991. return data_get($item, $value);
  992. };
  993. }
  994. /**
  995. * Zip the collection together with one or more arrays.
  996. *
  997. * e.g. new Collection([1, 2, 3])->zip([4, 5, 6]);
  998. * => [[1, 4], [2, 5], [3, 6]]
  999. *
  1000. * @param mixed ...$items
  1001. * @return static
  1002. */
  1003. public function zip($items)
  1004. {
  1005. $arrayableItems = array_map(function ($items) {
  1006. return $this->getArrayableItems($items);
  1007. }, func_get_args());
  1008. $params = array_merge([function () {
  1009. return new static(func_get_args());
  1010. }, $this->items], $arrayableItems);
  1011. return new static(call_user_func_array('array_map', $params));
  1012. }
  1013. /**
  1014. * Get the collection of items as a plain array.
  1015. *
  1016. * @return array
  1017. */
  1018. public function toArray()
  1019. {
  1020. return array_map(function ($value) {
  1021. return $value instanceof Arrayable ? $value->toArray() : $value;
  1022. }, $this->items);
  1023. }
  1024. /**
  1025. * Convert the object into something JSON serializable.
  1026. *
  1027. * @return array
  1028. */
  1029. public function jsonSerialize()
  1030. {
  1031. return array_map(function ($value) {
  1032. if ($value instanceof JsonSerializable) {
  1033. return $value->jsonSerialize();
  1034. } elseif ($value instanceof Jsonable) {
  1035. return json_decode($value->toJson(), true);
  1036. } elseif ($value instanceof Arrayable) {
  1037. return $value->toArray();
  1038. } else {
  1039. return $value;
  1040. }
  1041. }, $this->items);
  1042. }
  1043. /**
  1044. * Get the collection of items as JSON.
  1045. *
  1046. * @param int $options
  1047. * @return string
  1048. */
  1049. public function toJson($options = 0)
  1050. {
  1051. return json_encode($this->jsonSerialize(), $options);
  1052. }
  1053. /**
  1054. * Get an iterator for the items.
  1055. *
  1056. * @return \ArrayIterator
  1057. */
  1058. public function getIterator()
  1059. {
  1060. return new ArrayIterator($this->items);
  1061. }
  1062. /**
  1063. * Get a CachingIterator instance.
  1064. *
  1065. * @param int $flags
  1066. * @return \CachingIterator
  1067. */
  1068. public function getCachingIterator($flags = CachingIterator::CALL_TOSTRING)
  1069. {
  1070. return new CachingIterator($this->getIterator(), $flags);
  1071. }
  1072. /**
  1073. * Count the number of items in the collection.
  1074. *
  1075. * @return int
  1076. */
  1077. public function count()
  1078. {
  1079. return count($this->items);
  1080. }
  1081. /**
  1082. * Get a base Support collection instance from this collection.
  1083. *
  1084. * @return \Illuminate\Support\Collection
  1085. */
  1086. public function toBase()
  1087. {
  1088. return new self($this);
  1089. }
  1090. /**
  1091. * Determine if an item exists at an offset.
  1092. *
  1093. * @param mixed $key
  1094. * @return bool
  1095. */
  1096. public function offsetExists($key)
  1097. {
  1098. return array_key_exists($key, $this->items);
  1099. }
  1100. /**
  1101. * Get an item at a given offset.
  1102. *
  1103. * @param mixed $key
  1104. * @return mixed
  1105. */
  1106. public function offsetGet($key)
  1107. {
  1108. return $this->items[$key];
  1109. }
  1110. /**
  1111. * Set the item at a given offset.
  1112. *
  1113. * @param mixed $key
  1114. * @param mixed $value
  1115. * @return void
  1116. */
  1117. public function offsetSet($key, $value)
  1118. {
  1119. if (is_null($key)) {
  1120. $this->items[] = $value;
  1121. } else {
  1122. $this->items[$key] = $value;
  1123. }
  1124. }
  1125. /**
  1126. * Unset the item at a given offset.
  1127. *
  1128. * @param string $key
  1129. * @return void
  1130. */
  1131. public function offsetUnset($key)
  1132. {
  1133. unset($this->items[$key]);
  1134. }
  1135. /**
  1136. * Convert the collection to its string representation.
  1137. *
  1138. * @return string
  1139. */
  1140. public function __toString()
  1141. {
  1142. return $this->toJson();
  1143. }
  1144. /**
  1145. * Results array of items from Collection or Arrayable.
  1146. *
  1147. * @param mixed $items
  1148. * @return array
  1149. */
  1150. protected function getArrayableItems($items)
  1151. {
  1152. if (is_array($items)) {
  1153. return $items;
  1154. } elseif ($items instanceof self) {
  1155. return $items->all();
  1156. } elseif ($items instanceof Arrayable) {
  1157. return $items->toArray();
  1158. } elseif ($items instanceof Jsonable) {
  1159. return json_decode($items->toJson(), true);
  1160. } elseif ($items instanceof JsonSerializable) {
  1161. return $items->jsonSerialize();
  1162. } elseif ($items instanceof Traversable) {
  1163. return iterator_to_array($items);
  1164. }
  1165. return (array) $items;
  1166. }
  1167. }