LFT
  • Namespace
  • Class
  • Tree

Namespaces

  • Docoflow
    • Contracts
    • Entity
    • Facades
    • Models
    • Traits
  • Docolight
    • Agno
      • Traits
    • Container
    • Http
      • Contracts
    • Rest
      • Handler
      • Http
    • Support
      • Debug
      • Traits
  • Docotory
    • Traits
  • None

Classes

  • Docoflow\Docoflow
  • Docoflow\Entity\Group
  • Docoflow\Entity\Step
  • Docoflow\Entity\Verificator
  • Docoflow\Facades\Action
  • Docoflow\Facades\Activity
  • Docoflow\Facades\Flo
  • Docoflow\Facades\StateActivity
  • Docoflow\Flo
  • Docoflow\Models\Workflow
  • Docoflow\Models\WorkflowAction
  • Docoflow\Models\WorkflowActivity
  • Docoflow\Models\WorkflowGroups
  • Docoflow\Models\WorkflowNotification
  • Docoflow\Models\WorkflowState
  • Docoflow\Models\WorkflowStateActivity
  • Docoflow\Models\WorkflowStep
  • Docoflow\Models\WorkflowVerificator
  • Docolight
  • Docolight\Agno\AgnoModule
  • Docolight\Container\Container
  • Docolight\Http\Headers
  • Docolight\Http\JsonResponse
  • Docolight\Http\MimeResponse
  • Docolight\Http\Response
  • Docolight\Http\ResponseFactory
  • Docolight\Rest\Handler\RestfulErrorHandler
  • Docolight\Rest\Http\RestFulController
  • Docolight\Support\ActiveRecordWrapper
  • Docolight\Support\Arr
  • Docolight\Support\Carbonate
  • Docolight\Support\ClassLoader
  • Docolight\Support\Collection
  • Docolight\Support\CollectionDataProvider
  • Docolight\Support\Debug\Dumper
  • Docolight\Support\Debug\HtmlDumper
  • Docolight\Support\Facade
  • Docolight\Support\Factory
  • Docolight\Support\Fluent
  • Docolight\Support\Html
  • Docolight\Support\IterablePager
  • Docolight\Support\Repository
  • Docolight\Support\Set
  • Docolight\Support\Str
  • Docotory\Factory

Interfaces

  • Docoflow\Contracts\DocoflowContract
  • Docoflow\Contracts\ValidationStatus
  • Docolight\Http\Contracts\Arrayable

Traits

  • Docoflow\Traits\BulkValidator
  • Docoflow\Traits\Entity
  • Docoflow\Traits\HasMutator
  • Docoflow\Traits\Validable
  • Docolight\Agno\Traits\HasAssetsUrl
  • Docolight\Agno\Traits\HasAutoload
  • Docolight\Support\Traits\Macroable
  • Docotory\Traits\HasFactories

Exceptions

  • Docolight\Container\BindingResolutionException
  • Docotory\ResolvingTypeException

Functions

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