├── .gitbook.yaml ├── .github └── FUNDING.yml ├── .gitignore ├── .travis.yml ├── LICENSE ├── README.md ├── _config.yml ├── composer.json ├── docs ├── README.md ├── SUMMARY.md ├── common-methods │ ├── clone.md │ ├── get-getnestedelement.md │ ├── getkeysarray.md │ ├── has.md │ ├── remove.md │ └── set-setnestedelement.md ├── manipulating-array │ ├── computation.md │ ├── filtering.md │ ├── flattening.md │ ├── grouping.md │ ├── mapping.md │ └── sorting.md ├── object-oriented-methods │ └── general-information.md ├── traversing-array │ ├── finding.md │ └── iterating.md ├── utility-methods │ ├── forcearray.md │ ├── getdepth.md │ ├── getfirstkey.md │ ├── getfirstvalue.md │ ├── getlastkey.md │ ├── getlastvalue.md │ ├── nth.md │ ├── pack.md │ ├── random.md │ ├── shuffle.md │ ├── unpack.md │ └── untitled.md └── validating-array │ ├── check.md │ ├── haskeys.md │ ├── isarrayofarrays.md │ ├── isassoc.md │ ├── isempty.md │ ├── isnested.md │ ├── isnumeric.md │ └── isunique.md ├── phpunit.xml ├── src ├── Arr.php └── ArrObj.php └── tests ├── Arr └── ArrTest.php ├── ArrObj └── ArrObjTest.php └── ArrTestCase.php /.gitbook.yaml: -------------------------------------------------------------------------------- 1 | root: ./docs/ 2 | 3 | structure: 4 | readme: README.md 5 | summary: SUMMARY.md -------------------------------------------------------------------------------- /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | # These are supported funding model platforms 2 | 3 | github: minwork # Replace with up to 4 GitHub Sponsors-enabled usernames e.g., [user1, user2] 4 | patreon: # Replace with a single Patreon username 5 | open_collective: # Replace with a single Open Collective username 6 | ko_fi: # Replace with a single Ko-fi username 7 | tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel 8 | community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry 9 | liberapay: # Replace with a single Liberapay username 10 | issuehunt: # Replace with a single IssueHunt username 11 | otechie: # Replace with a single Otechie username 12 | lfx_crowdfunding: # Replace with a single LFX Crowdfunding project-name e.g., cloud-foundry 13 | custom: # Replace with up to 4 custom sponsorship URLs e.g., ['link1', 'link2'] 14 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .idea/ 2 | .settings/ 3 | .buildpath 4 | .project 5 | composer.lock 6 | vendor/ 7 | build/ -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: php 2 | 3 | php: 4 | - 7.1 5 | - 7.2 6 | - 7.3 7 | branches: 8 | only: 9 | - master 10 | before_install: 11 | - travis_retry composer self-update 12 | - composer install 13 | script: 14 | - mkdir -p build/logs 15 | - vendor/bin/phpunit --testsuite Complex 16 | after_script: 17 | - travis_retry vendor/bin/php-coveralls 18 | # or enable logging 19 | - travis_retry vendor/bin/php-coveralls -v -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2018 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Minwork Array 2 | 3 | [![Build Status](https://camo.githubusercontent.com/e98c32cb27c2f579cc8a8472235668692d3ef75f/68747470733a2f2f7472617669732d63692e6f72672f6d696e776f726b2f61727261792e7376673f6272616e63683d6d6173746572)](https://travis-ci.org/minwork/array) [![Coverage Status](https://camo.githubusercontent.com/5597efd400c8dc6e11b7e0246ad03de2c5437b2a/68747470733a2f2f636f766572616c6c732e696f2f7265706f732f6769746875622f6d696e776f726b2f61727261792f62616467652e7376673f6272616e63683d6d6173746572)](https://coveralls.io/github/minwork/array?branch=master) [![Latest Stable Version](https://img.shields.io/packagist/v/minwork/array)](https://packagist.org/packages/minwork/array) [![Github Stars](https://img.shields.io/github/stars/minwork/array?style=social)](https://github.com/minwork/array) 4 | 5 | ## Pack of array convenience methods for handling: 6 | * **Nested** arrays 7 | * Arrays of **objects** 8 | * **Associative** arrays 9 | * **Chaining** array transformations 10 | ### Easily **create**, **access**, **validate**, **manipulate** and **transform** arrays 11 | Advanced implementation of well known operations: 12 | * [Get](https://minwork.gitbook.io/array/common-methods/get-getnestedelement) 13 | * [Set](https://minwork.gitbook.io/array/common-methods/set-setnestedelement) 14 | * [Has](https://minwork.gitbook.io/array/common-methods/has) 15 | * [Map](https://minwork.gitbook.io/array/manipulating-array/mapping) 16 | * [Each](https://minwork.gitbook.io/array/traversing-array/iterating) 17 | * [Filter](https://minwork.gitbook.io/array/manipulating-array/filtering) 18 | * [Find](https://minwork.gitbook.io/array/traversing-array/finding) 19 | * [Group](https://minwork.gitbook.io/array/manipulating-array/grouping) 20 | * [Sort](https://minwork.gitbook.io/array/manipulating-array/sorting) 21 | * [Check](https://minwork.gitbook.io/array/validating-array/check) 22 | * [And many more...](https://minwork.gitbook.io/array/) 23 | 24 | ## Installation 25 | 26 | `composer require minwork/array` 27 | 28 | ## Advantages 29 | 30 | * Thoroughly **tested** 31 | * Well **documented** 32 | * Leverages PHP 7 syntax and **speed** 33 | * No external dependencies 34 | * Large variety of usages 35 | 36 | ## Example of usage 37 | ```php 38 | // Set nested array value 39 | $array = Arr::set([], 'key1.key2.key3', 'my_value'); 40 | // Which is equivalent to 41 | [ 42 | 'key1' => [ 43 | 'key2' => [ 44 | 'key3' => 'my_value' 45 | ] 46 | ] 47 | ] 48 | 49 | // Get nested array value 50 | Arr::get($array, 'key1.key2') -> ['key3' => 'my_value'] 51 | 52 | // Check if array has nested element 53 | Arr::has($array, 'key1.key2.key3') -> true 54 | 55 | // Map array while accessing it's key 56 | Arr::map($array, function ($key, $value) { 57 | // Your code here 58 | }); 59 | 60 | // Find array element 61 | Arr::find($array, function ($element) { 62 | return Arr::get($element, 'key2.key3') === 'my_value'; 63 | }) -> [ 'key2' => [ 'key3' => 'my_value'] ] 64 | 65 | // Chain few methods 66 | Arr::obj(['test' => 1, 'foo' => 'bar']) 67 | ->set('abc', 123) 68 | ->set('[]', 'auto_index') 69 | ->remove('foo') 70 | ->getArray() 71 | -> 72 | [ 73 | 'test' => 1, 74 | 'abc' => 123, 75 | 'auto_index' 76 | ] 77 | 78 | // Group objects by the result of calling method 'getSize' on each object 79 | Arr::groupObjects([$cat, $dog, $fish, ...], 'getSize') -> 80 | [ 81 | 'medium' => [$cat, $dog, ...], 82 | 'small' => [$fish, ...], 83 | ... 84 | ] 85 | ``` 86 | 87 | ## Documentation 88 | 89 | [https://minwork.gitbook.io/array/](https://minwork.gitbook.io/array/) 90 | 91 | -------------------------------------------------------------------------------- /_config.yml: -------------------------------------------------------------------------------- 1 | theme: jekyll-theme-midnight -------------------------------------------------------------------------------- /composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name" : "minwork/array", 3 | "description" : "Pack of advanced array functions specifically tailored for: associative (assoc) array, multidimensional array, array of objects and handling nested array elements", 4 | "type" : "library", 5 | "keywords" : [ 6 | "array", 7 | "arrays", 8 | "assoc", 9 | "multidimensional", 10 | "objects", 11 | "helper", 12 | "associative", 13 | "php 7" 14 | ], 15 | "license" : "MIT", 16 | "authors" : [{ 17 | "name" : "Christopher Kalkhoff", 18 | "email" : "krzysztof.kalkhoff@gmail.com", 19 | "role" : "Founder" 20 | } 21 | ], 22 | "require" : { 23 | "php" : ">=7.1" 24 | }, 25 | "require-dev" : { 26 | "phpunit/phpunit" : "^7.0", 27 | "php-coveralls/php-coveralls": "^2.1" 28 | }, 29 | "autoload" : { 30 | "psr-4" : { 31 | "Minwork\\Helper\\" : "src/" 32 | } 33 | }, 34 | "autoload-dev" : { 35 | "psr-4" : { 36 | "Minwork\\Helper\\Tests\\" : "tests/" 37 | } 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /docs/README.md: -------------------------------------------------------------------------------- 1 | # Minwork Array 2 | 3 | ## Welcome to the documentation page 4 | 5 | Minwork Array library is focused on conviniently handling nested arrays as well as arrays of objects. 6 | 7 | {% hint style="info" %} 8 | Detailed documentation is always available through PHPDoc in your editor, so you can access it anytime. 9 | {% endhint %} 10 | 11 | I believe that the best way to learn some code is to see it in action. That's why within this documentation, aside from detailed specification of each method you will find various examples of using it which will help in faster understanding it's purpose and applications. 12 | 13 | To quickly get started check out the links below or look at the full list of available methods in the left panel. 14 | 15 | {% page-ref page="common-methods/has.md" %} 16 | 17 | {% page-ref page="common-methods/get-getnestedelement.md" %} 18 | 19 | {% page-ref page="common-methods/set-setnestedelement.md" %} 20 | 21 | {% page-ref page="common-methods/remove.md" %} 22 | 23 | {% page-ref page="utility-methods/getfirstkey.md" %} 24 | 25 | {% page-ref page="utility-methods/getfirstvalue.md" %} 26 | 27 | -------------------------------------------------------------------------------- /docs/SUMMARY.md: -------------------------------------------------------------------------------- 1 | # Table of contents 2 | 3 | * [Minwork Array](README.md) 4 | 5 | ## Common methods 6 | 7 | * [has](common-methods/has.md) 8 | * [get → getNestedElement](common-methods/get-getnestedelement.md) 9 | * [set → setNestedElement](common-methods/set-setnestedelement.md) 10 | * [remove](common-methods/remove.md) 11 | * [clone](common-methods/clone.md) 12 | * [getKeysArray](common-methods/getkeysarray.md) 13 | 14 | ## Object oriented methods 15 | 16 | * [General information](object-oriented-methods/general-information.md) 17 | 18 | ## Traversing array 19 | 20 | * [Finding](traversing-array/finding.md) 21 | * [Iterating](traversing-array/iterating.md) 22 | 23 | ## Manipulating array 24 | 25 | * [Mapping](manipulating-array/mapping.md) 26 | * [Filtering](manipulating-array/filtering.md) 27 | * [Grouping](manipulating-array/grouping.md) 28 | * [Sorting](manipulating-array/sorting.md) 29 | * [Computations](manipulating-array/computation.md) 30 | * [Flattening](manipulating-array/flattening.md) 31 | 32 | ## Validating array 33 | 34 | * [check](validating-array/check.md) 35 | * [isEmpty](validating-array/isempty.md) 36 | * [isNested](validating-array/isnested.md) 37 | * [isArrayOfArrays](validating-array/isarrayofarrays.md) 38 | * [isAssoc](validating-array/isassoc.md) 39 | * [isUnique](validating-array/isunique.md) 40 | * [isNumeric](validating-array/isnumeric.md) 41 | * [hasKeys](validating-array/haskeys.md) 42 | 43 | ## Utility methods 44 | 45 | * [pack](utility-methods/pack.md) 46 | * [unpack](utility-methods/unpack.md) 47 | * [createMulti](utility-methods/untitled.md) 48 | * [forceArray](utility-methods/forcearray.md) 49 | * [getDepth](utility-methods/getdepth.md) 50 | * [random](utility-methods/random.md) 51 | * [shuffle](utility-methods/shuffle.md) 52 | * [nth](utility-methods/nth.md) 53 | * [getFirstKey](utility-methods/getfirstkey.md) 54 | * [getLastKey](utility-methods/getlastkey.md) 55 | * [getFirstValue](utility-methods/getfirstvalue.md) 56 | * [getLastValue](utility-methods/getlastvalue.md) 57 | 58 | -------------------------------------------------------------------------------- /docs/common-methods/clone.md: -------------------------------------------------------------------------------- 1 | # clone 2 | 3 | #### Definition 4 | 5 | ```php 6 | Arr::clone(array $array): array 7 | ``` 8 | 9 | #### Description 10 | 11 | Copy array and clone every object inside it 12 | 13 | #### Examples 14 | 15 | ```php 16 | $object = new class() { 17 | public $counter = 1; 18 | 19 | function __clone() 20 | { 21 | $this->counter = 2; 22 | } 23 | }; 24 | 25 | $array = [ 26 | 'foo', 27 | 'bar', 28 | $object, 29 | 'test', 30 | 'nested' => [ 31 | 'object' => $object 32 | ] 33 | ]; 34 | 35 | $cloned = Arr::clone($array); 36 | 37 | $cloned[0] -> 'foo' 38 | $cloned[2]->counter -> 2 39 | $cloned['nested']['object']->counter -> 2 40 | ``` 41 | 42 | -------------------------------------------------------------------------------- /docs/common-methods/get-getnestedelement.md: -------------------------------------------------------------------------------- 1 | # get → getNestedElement 2 | 3 | #### Definition 4 | 5 | ```php 6 | Arr::getNestedElement(array|ArrayAccess $array, mixed $keys, mixed $default = null): mixed 7 | ``` 8 | 9 | #### Aliases 10 | 11 | ```php 12 | get($array, $keys, $default = null) -> getNestedElement($array, $keys, $default) 13 | ``` 14 | 15 | #### Description 16 | 17 | Get nested array element using specified keys or return `$default` value if it does not exists. 18 | 19 | {% hint style="info" %} 20 | `$keys` argument is parsed using [getKeysArray ](getkeysarray.md)method 21 | {% endhint %} 22 | 23 | #### Examples 24 | 25 | ```php 26 | $array = ['key1' => ['key2' => ['key3' => ['test']]]]; 27 | 28 | Arr::getNestedElement($array, 'key1.key2.key3') -> ['test'] 29 | 30 | Arr::getNestedElement($array, 'key1.key2.key3.0') -> 'test' 31 | 32 | Arr::getNestedElement($array, ['nonexistent', 'key'], 'default') -> 'default' 33 | 34 | Arr::getNestedElement($array, 'nonexistent.key.without.default') -> null 35 | ``` 36 | 37 | -------------------------------------------------------------------------------- /docs/common-methods/getkeysarray.md: -------------------------------------------------------------------------------- 1 | # getKeysArray 2 | 3 | #### Definition 4 | 5 | ```php 6 | Arr::getKeysArray(mixed $keys): array 7 | ``` 8 | 9 | #### Description 10 | 11 | Transform variable into standardised array of keys. 12 | 13 | This method filters out any values that cannot be used as array key leaving only not empty strings and integers as seen in the example below. 14 | 15 | {% hint style="info" %} 16 | All `$keys` arguments in other methods are normalized using this method 17 | {% endhint %} 18 | 19 | #### Examples 20 | 21 | ```php 22 | Arr::getKeysArray(0) -> [0] 23 | 24 | Arr::getKeysArray(null) -> [] 25 | 26 | Arr::getKeysArray('key') -> ['key'] 27 | 28 | Arr::getKeysArray('key1.0.key2.1') -> ['key1', '0', 'key2', '1'] 29 | 30 | Arr::getKeysArray([null, 'key1', '', 'key2', 3.1415, 0]) -> ['key1', 'key2', 0] 31 | ``` 32 | 33 | -------------------------------------------------------------------------------- /docs/common-methods/has.md: -------------------------------------------------------------------------------- 1 | # has 2 | 3 | #### Definition 4 | 5 | ```php 6 | Arr::has(array $array, mixed $keys): bool 7 | ``` 8 | 9 | #### Description 10 | 11 | Check if specified \(nested\) key\(s\) exists in array 12 | 13 | {% hint style="info" %} 14 | `$keys` argument is parsed using [getKeysArray ](getkeysarray.md)method 15 | {% endhint %} 16 | 17 | #### Examples 18 | 19 | ```php 20 | $array = [ 21 | 'foo' => [ 22 | 1, 23 | 'test' => [ 24 | 'abc' => 2, 25 | 'def' 26 | ], 27 | [ 28 | 'bar' => true 29 | ], 30 | ], 31 | ]; 32 | 33 | Arr::has($array, 'foo') -> true 34 | Arr::has($array, 'foo.0') -> true 35 | Arr::has($array, 'foo.test') -> true 36 | Arr::has($array, 'foo.test.abc') -> true 37 | Arr::has($array, ['foo', 1, 'bar']) -> true 38 | 39 | Arr::has($array, 'test') -> false 40 | Arr::has($array, []) -> false 41 | Arr::has($array, 'not.existing.key') -> false 42 | ``` 43 | 44 | -------------------------------------------------------------------------------- /docs/common-methods/remove.md: -------------------------------------------------------------------------------- 1 | # remove 2 | 3 | #### Definition 4 | 5 | ```php 6 | Arr::remove(array $array, $keys): array 7 | ``` 8 | 9 | #### Description 10 | 11 | Remove element inside array at path specified by keys. 12 | 13 | {% hint style="info" %} 14 | `$keys` argument is parsed using [getKeysArray ](getkeysarray.md)method 15 | {% endhint %} 16 | 17 | #### Examples 18 | 19 | ```php 20 | $array = [ 21 | 'foo' => [ 22 | 1, 23 | 'test' => [ 24 | 'abc' => 2, 25 | 'def' 26 | ], 27 | [ 28 | 'bar' => true 29 | ], 30 | ], 31 | ]; 32 | 33 | Arr::remove($array, 'foo') -> [] 34 | Arr::remove($array, '') -> $array 35 | Arr::remove($array, []) -> $array 36 | 37 | Arr::remove($array, 'foo.test.abc') -> 38 | [ 39 | 'foo' => [ 40 | 1, 41 | 'test' => [ 42 | // Removed 43 | //'abc' => 2, 44 | 'def' 45 | ], 46 | [ 47 | 'bar' => true 48 | ], 49 | ], 50 | ] 51 | 52 | Arr::remove($array, 'foo.test') -> 53 | [ 54 | 'foo' => [ 55 | 1, 56 | // Removed 57 | /*'test' => [ 58 | 'abc' => 2, 59 | 'def' 60 | ],*/ 61 | [ 62 | 'bar' => true 63 | ], 64 | ], 65 | ] 66 | 67 | Arr::remove($array, ['foo', 1, 'bar']) -> 68 | [ 69 | 'foo' => [ 70 | 1, 71 | 'test' => [ 72 | 'abc' => 2, 73 | 'def' 74 | ], 75 | [ 76 | // Removed 77 | //'bar' => true 78 | ], 79 | ], 80 | ] 81 | ``` 82 | 83 | -------------------------------------------------------------------------------- /docs/common-methods/set-setnestedelement.md: -------------------------------------------------------------------------------- 1 | # set → setNestedElement 2 | 3 | #### Definition 4 | 5 | ```php 6 | Arr::setNestedElement(array|ArrayAccess $array, mixed $keys, mixed $value): array|ArrayAccess 7 | ``` 8 | 9 | #### Aliases 10 | 11 | ```php 12 | set(array|ArrayAccess $array, $keys, $value) -> setNestedElement(array|ArrayAccess $array, $keys, $value) 13 | ``` 14 | 15 | #### Description 16 | 17 | Set array element specified by keys to the desired value \(create missing keys if necessary\). 18 | 19 | {% hint style="info" %} 20 | `$keys` argument is parsed using [getKeysArray ](getkeysarray.md)method 21 | {% endhint %} 22 | 23 | #### Examples 24 | 25 | ```php 26 | $array = ['key1' => ['key2' => ['key3' => ['test']]]]; 27 | 28 | Arr::setNestedElement([], 'key1.key2.key3', ['test']) -> $array 29 | 30 | $array = Arr::setNestedElement($array, 'key1.key2.key4', 'test2'); 31 | $array['key1']['key2']['key4'] -> 'test2' 32 | 33 | // Create nested array element using automatic index 34 | Arr::setNestedElement($array, 'foo.[].foo', 'bar') -> 35 | [ 36 | 'foo' => [ 37 | [ 38 | 'foo' => 'bar', 39 | ], 40 | ], 41 | ] 42 | 43 | Arr::setNestedElement([], '[].[].[]', 'test') -> [ [ [ 'test' ] ] ] 44 | ``` 45 | 46 | -------------------------------------------------------------------------------- /docs/manipulating-array/computation.md: -------------------------------------------------------------------------------- 1 | # Computations 2 | 3 | ## sum 4 | 5 | #### Definition 6 | 7 | ```php 8 | Arr::sum(array ...$arrays): array 9 | ``` 10 | 11 | #### Description 12 | 13 | Sum associative arrays by their keys into one array 14 | 15 | #### Examples 16 | 17 | ```php 18 | $arrays = [ 19 | [ 20 | 'a' => 1, 21 | 'b' => -3.5, 22 | 'c' => 0, 23 | 3 24 | ], 25 | [ 26 | 2, 27 | 'a' => 0, 28 | 'c' => -5, 29 | 'd' => PHP_INT_MAX, 30 | ], 31 | [ 32 | -5, 33 | 'b' => 3.5, 34 | 'a' => -1, 35 | 'c' => 5, 36 | ], 37 | [ 38 | 'd' => PHP_INT_MAX, 39 | ], 40 | [ 41 | 'd' => 2 * -PHP_INT_MAX, 42 | ] 43 | ]; 44 | 45 | Arr::sum(...$arrays) -> 46 | [ 47 | 0, 48 | 'a' => 0, 49 | 'b' => 0, 50 | 'c' => 0, 51 | 'd' => 0, 52 | ] 53 | 54 | Arr::sum([null, '', false], ['1', true, 'test']) -> [1, 1, 0] 55 | ``` 56 | 57 | ## diffObjects 58 | 59 | #### Declaration 60 | 61 | ```php 62 | Arr::diffObjects(array $array1, array $array2, array ...$arrays): array 63 | ``` 64 | 65 | #### Description 66 | 67 | Compute difference between two or more arrays of objects 68 | 69 | #### Examples 70 | 71 | ```php 72 | $object1 = new \stdClass(); 73 | $object2 = new \stdClass(); 74 | $object3 = new \stdClass(); 75 | 76 | Arr::diffObjects( 77 | [$object3, $object1, $object2], 78 | [$object3], [$object2] 79 | ) -> [1 => $object1] 80 | 81 | Arr::diffObjects( 82 | [$object3, $object1, $object2], 83 | [$object3], 84 | [$object1, $object2] 85 | ) -> [] 86 | 87 | Arr::diffObjects( 88 | [$object1], 89 | [$object3], 90 | [$object2], 91 | [] 92 | ) -> [$object1] 93 | ``` 94 | 95 | ## intersectObjects 96 | 97 | #### Definition 98 | 99 | ```php 100 | Arr::intersectObjects(array $array1, array $array2, array ...$arrays): array 101 | ``` 102 | 103 | #### Description 104 | 105 | Compute intersection between two or more arrays of objects 106 | 107 | #### Examples 108 | 109 | ```php 110 | $object1 = new \stdClass(); 111 | $object2 = new \stdClass(); 112 | $object3 = new \stdClass(); 113 | 114 | Arr::intersectObjects( 115 | [$object3, $object1, $object2], 116 | [$object3, $object2], 117 | [$object2] 118 | ) -> [2 => $object2] 119 | 120 | Arr::intersectObjects( 121 | [$object3, $object1, $object2], 122 | [$object3], 123 | [$object1, $object2] 124 | ) -> [] 125 | 126 | Arr::intersectObjects( 127 | [$object1, $object2, $object3, $object1], 128 | [$object1, $object2] 129 | ) -> [$object1, $object2, 3 => $object1] 130 | ``` 131 | 132 | -------------------------------------------------------------------------------- /docs/manipulating-array/filtering.md: -------------------------------------------------------------------------------- 1 | # Filtering 2 | 3 | ## filter 4 | 5 | #### Definition 6 | 7 | ```php 8 | Arr::filter(array $array, ?callable $callback = null, int $flag = 0): array 9 | ``` 10 | 11 | #### Description 12 | 13 | Wrapper around PHP built-in [array\_filter](https://www.php.net/manual/en/function.array-filter.php) method to allow [chaining](https://minwork.gitbook.io/array/object-oriented-methods/general-information#chaining) in `ArrObj` 14 | 15 | #### Examples 16 | 17 | See [array\_filter examples](https://www.php.net/manual/en/function.array-filter.php#refsect1-function.array-filter-examples) 18 | 19 | ## filterByKeys 20 | 21 | #### Definition 22 | 23 | ```php 24 | Arr::filterByKeys(array $array, mixed $keys, bool $exclude = false): array 25 | ``` 26 | 27 | #### Description 28 | 29 | Filter array values by preserving only those which keys are present in array obtained from $keys variable 30 | 31 | #### Examples 32 | 33 | ```php 34 | $array = [ 35 | 'a' => 1, 36 | 'b' => 2, 37 | 3 => 'c', 38 | 4 => 5 39 | ]; 40 | 41 | Arr::filterByKeys($array, 'a.b.3') -> ['a' => 1, 'b' => 2, 3 => 'c'] 42 | Arr::filterByKeys($array, 'a.b.3', true) -> [4 => 5] 43 | 44 | Arr::filterByKeys($array, [null, 0, '']) -> [] 45 | Arr::filterByKeys($array, [null, 0, ''], true) -> $array 46 | ``` 47 | 48 | ## filterObjects 49 | 50 | #### Definition 51 | 52 | ```php 53 | Arr::filterObjects(array $objects, string $method, ...$args): array 54 | ``` 55 | 56 | #### Description 57 | 58 | Filter objects array using return value of specified method 59 | 60 | This method also filter values other than objects by standard boolean comparison 61 | 62 | #### Examples 63 | 64 | ```php 65 | $object = new class() { 66 | function test($preserve = true) { 67 | return $preserve; 68 | } 69 | }; 70 | 71 | $array = [$object, 'foo', $object, false]; 72 | 73 | Arr::filterObjects($array, 'test') -> [$object, 'foo', $object] 74 | Arr::filterObjects($array, 'test', false) -> ['foo'] 75 | ``` 76 | 77 | -------------------------------------------------------------------------------- /docs/manipulating-array/flattening.md: -------------------------------------------------------------------------------- 1 | # Flattening 2 | 3 | ## flatten 4 | 5 | #### Definition 6 | 7 | ```php 8 | Arr::flatten(array $array, ?int $depth = null, bool $assoc = false): array 9 | ``` 10 | 11 | #### Description 12 | 13 | Flatten array of arrays to a n-depth array 14 | 15 | #### Examples 16 | 17 | ```php 18 | $array = [ 19 | 'a' => [ 20 | 'b' => [ 21 | 'c' => 'test' 22 | ], 23 | 'd' => 1 24 | ], 25 | 'b' => [ 26 | 'e' => 2 27 | ] 28 | ]; 29 | 30 | Arr::flatten($array) -> 31 | [ 32 | 'test', 33 | 1, 34 | 2 35 | ] 36 | Arr::flatten($array, 1) -> 37 | [ 38 | ['c' => 'test'], 39 | 1, 40 | 2 41 | ] 42 | Arr::flatten($array, 0) -> 43 | [ 44 | [ 45 | 'b' => [ 46 | 'c' => 'test' 47 | ], 48 | 'd' => 1 49 | ], 50 | [ 51 | 'e' => 2 52 | ] 53 | ] 54 | 55 | Arr::flatten([[[[]]]]) -> [] 56 | 57 | // When $assoc is set to true this method will try to preserve as much string keys as possible using automatically generated numeric indexes as fallback 58 | Arr::flatten($array, null, true) -> 59 | [ 60 | 'c' => 'test', 61 | 'd' => 1, 62 | 'e' => 2 63 | ] 64 | 65 | $array = [ 66 | 'a' => [ 67 | 'b' => [ 68 | 'c' => 1, 69 | ], 70 | ], 71 | [ 72 | 'c' => 2 73 | ] 74 | ]; 75 | 76 | // Here key 'c' is duplicated so it will fallback to numeric index 77 | Arr::flatten($array, null, true) -> 78 | [ 79 | 'c' => 1, 80 | 2, 81 | ] 82 | ``` 83 | 84 | ## flattenSingle 85 | 86 | #### Definition 87 | 88 | ```php 89 | Arr::flattenSingle(array $array): array 90 | ``` 91 | 92 | #### Description 93 | 94 | Flatten single element arrays \(also nested single element arrays\) 95 | 96 | #### Examples 97 | 98 | ```php 99 | $array = [ 100 | 'a' => ['test'], 101 | 'b' => [ 102 | 'test2', 103 | 'c' => ['test3'] 104 | ] 105 | ]; 106 | 107 | Arr::flattenSingle($array) -> 108 | [ 109 | 'a' => 'test', 110 | 'b' => [ 111 | 'test2', 112 | 'c' => 'test3' 113 | ], 114 | ] 115 | 116 | $array = [ 117 | 'a' => [ 118 | 'b' => 1 119 | ], 120 | 'b' => 2, 121 | ]; 122 | 123 | Arr::flattenSingle($array) -> ['a' => 1, 'b' => 2] 124 | 125 | Arr::flattenSingle([['a']]) -> ['a'] 126 | 127 | Arr::flattenSingle([]) -> [] 128 | ``` 129 | 130 | -------------------------------------------------------------------------------- /docs/manipulating-array/grouping.md: -------------------------------------------------------------------------------- 1 | # Grouping 2 | 3 | ## group 4 | 5 | #### Definition 6 | 7 | ```php 8 | Arr::group(array $array, string|int $key): array 9 | ``` 10 | 11 | #### Description 12 | 13 | Group array of arrays by value of element with specified key 14 | 15 | #### Examples 16 | 17 | ```php 18 | $array = [ 19 | 'a' => ['key1' => 'test1', 'key2' => 1, 'key3' => 'a'], 20 | 'b' => ['key1' => 'test1', 'key2' => 2], 21 | 2 => ['key1' => 'test2', 'key2' => 3, 'key3' => 'b'] 22 | ]; 23 | 24 | Arr::group($array, 'key1') -> 25 | [ 26 | 'test1' => [ 27 | 'a' => ['key1' => 'test1', 'key2' => 1, 'key3' => 'a'], 28 | 'b' => ['key1' => 'test1', 'key2' => 2] 29 | ], 30 | 'test2' => [ 31 | 2 => ['key1' => 'test2', 'key2' => 3, 'key3' => 'b'] 32 | ], 33 | ] 34 | 35 | Arr::group($array, 'key2') -> 36 | [ 37 | 1 => [ 38 | 'a' => ['key1' => 'test1', 'key2' => 1, 'key3' => 'a'], 39 | ], 40 | 2 => [ 41 | 'b' => ['key1' => 'test1', 'key2' => 2] 42 | ], 43 | 3 => [ 44 | 2 => ['key1' => 'test2', 'key2' => 3, 'key3' => 'b'] 45 | ], 46 | ] 47 | 48 | Arr::group($array, 'key3') -> 49 | [ 50 | 'a' => [ 51 | 'a' => ['key1' => 'test1', 'key2' => 1, 'key3' => 'a'] 52 | ], 53 | 'b' => [ 54 | 2 => ['key1' => 'test2', 'key2' => 3, 'key3' => 'b'] 55 | ], 56 | ] 57 | 58 | Arr::group($array, 'key4') -> [] 59 | ``` 60 | 61 | ## groupObjects 62 | 63 | #### Definition 64 | 65 | ```php 66 | Arr::groupObjects(array $objects, string $method, ...$args): array 67 | ``` 68 | 69 | #### Description 70 | 71 | Group array of objects by value returned from specified method 72 | 73 | #### Examples 74 | 75 | ```php 76 | $object1 = new class() { 77 | function test() { 78 | return 'test1'; 79 | } 80 | }; 81 | $object2 = new class() { 82 | function test() { 83 | return 'test2'; 84 | } 85 | }; 86 | 87 | Arr::groupObjects([$object1, $object2, $object1], 'test') -> 88 | [ 89 | 'test1' => [$object1, $object1], 90 | 'test2' => [$object2], 91 | ] 92 | 93 | // This method is also very useful in conjunction with Arr::flattenSingle to assign unique key for each object 94 | Arr::flattenSingle(Arr::groupObjects([$object1, $object2], 'test')) -> 95 | [ 96 | 'test1' => $object1, 97 | 'test2' => $object2, 98 | ] 99 | ``` 100 | 101 | -------------------------------------------------------------------------------- /docs/manipulating-array/mapping.md: -------------------------------------------------------------------------------- 1 | # Mapping 2 | 3 | ## map 4 | 5 | #### Definition 6 | 7 | ```php 8 | Arr::map(array $array, callable $callback, int $mode = Arr::MAP_ARRAY_KEY_VALUE): array 9 | ``` 10 | 11 | #### Description 12 | 13 | Applies a callback to the elements of given array. Arguments supplied to callback differs depending on selected `$mode`. 14 | 15 | {% hint style="warning" %} 16 | For backward compatibility using `map(callable, array)` is still possible but is deprecated and will issue appropriate warning 17 | {% endhint %} 18 | 19 | #### Modes 20 | 21 | | Constant name | Description | 22 | | :--- | :--- | 23 | | MAP\_ARRAY\_KEY\_VALUE | Map array using callback in form of `function($key, $value)` | 24 | | MAP\_ARRAY\_VALUE\_KEYS\_LIST | Map array using callback in form of `function($value, $key1, $key2, ...)` | 25 | | MAP\_ARRAY\_KEYS\_ARRAY\_VALUE | Map array using callback in form of `function(array $keys, $value)` | 26 | | MAP\_ARRAY\_VALUE\_KEY | Map array using callback in form of `function($value, $key)` | 27 | 28 | #### Examples 29 | 30 | ```php 31 | $array1 = ['a', 'b', 'c']; 32 | $array2 = [ 33 | 1 => [ 34 | 2 => 'a', 35 | 3 => 'b', 36 | 4 => [ 37 | 5 => 'c', 38 | ], 39 | ], 40 | 'test' => 'd', 41 | ]; 42 | 43 | $mapKeyValue = function ($key, $value) { 44 | return "{$key} -> {$value}"; 45 | }; 46 | // Mind that $value is a first argument here 47 | $mapValueKey = function ($value, $key) { 48 | return "{$key} -> {$value}"; 49 | }; 50 | $mapKeysValue = function ($keys, $value) { 51 | return implode('.', $keys) . " -> {$value}"; 52 | }; 53 | $mapValueKeysList = function ($value, $key1, $key2) { 54 | return "$key1.$key2 -> {$value}"; 55 | }; 56 | 57 | // Equivalent to using MAP_ARRAY_KEY_VALUE as mode (3rd) argument 58 | Arr::map($array1, $mapKeyValue) -> ['0 -> a', '1 -> b', '2 -> c'] 59 | 60 | // Resemble array_map function but with array supplied as first argument 61 | Arr::map($array1, $mapValueKey) -> ['0 -> a', '1 -> b', '2 -> c'] 62 | 63 | // Map multidimensional array using keys array 64 | Arr::map($array2, $mapKeysValue, Arr::MAP_ARRAY_KEYS_ARRAY_VALUE) -> 65 | [ 66 | 1 => [ 67 | 2 => '1.2 -> a', 68 | 3 => '1.3 -> b', 69 | 4 => [ 70 | 5 => '1.4.5 -> c', 71 | ], 72 | ], 73 | 'test' => 'test -> d', 74 | ] 75 | 76 | // Map multidimensional array using keys list (mind that all keys above 2nd are ignored due to callback function syntax) 77 | Arr::map($array2, $mapValueKeysList, Arr::MAP_ARRAY_VALUE_KEYS_LIST) -> 78 | [ 79 | 1 => [ 80 | 2 => '1.2 -> a', 81 | 3 => '1.3 -> b', 82 | 4 => [ 83 | 5 => '1.4 -> c', 84 | ], 85 | ], 86 | 'test' => 'test -> d', 87 | ] 88 | ``` 89 | 90 | ## mapObjects 91 | 92 | #### Definition 93 | 94 | ```php 95 | Arr::mapObjects(array $objects, string $method, ...$args): array 96 | ``` 97 | 98 | #### Description 99 | 100 | Map array of object to values returned from objects method 101 | 102 | #### Examples 103 | 104 | ```php 105 | $object = new class() { 106 | function test($arg = 0) { 107 | return 1 + $arg; 108 | } 109 | }; 110 | $array = [$object, $object, $object]; 111 | 112 | Arr::mapObjects($array, 'test') -> [1, 1, 1] 113 | Arr::mapObjects($array, 'test', 2) -> [3, 3, 3] 114 | ``` 115 | 116 | -------------------------------------------------------------------------------- /docs/manipulating-array/sorting.md: -------------------------------------------------------------------------------- 1 | # Sorting 2 | 3 | ## orderByKeys 4 | 5 | #### Definition 6 | 7 | ```php 8 | Arr::orderByKeys(array $array, mixed $keys, bool $appendUnmatched = true): array 9 | ``` 10 | 11 | #### Description 12 | 13 | Order associative array according to supplied keys order 14 | 15 | #### Examples 16 | 17 | ```php 18 | $array = [ 19 | 'foo', 20 | 'a' => 'bar', 21 | 'b' => 'test', 22 | 1, 23 | 'c' => ['test' => 2] 24 | ]; 25 | 26 | Arr::orderByKeys($array, 'a.0.c.1.b') -> 27 | [ 28 | 'a' => 'bar', 29 | 0 => 'foo', 30 | 'c' => ['test' => 2], 31 | 1 => 1, 32 | 'b' => 'test', 33 | ] 34 | 35 | Arr::orderByKeys($array, 'a.0.c') -> 36 | [ 37 | 'a' => 'bar', 38 | 0 => 'foo', 39 | 'c' => ['test' => 2], 40 | 41 | 'b' => 'test', 42 | 1 => 1, 43 | ] 44 | 45 | Arr::orderByKeys($array, 'a.0.c', false) -> 46 | [ 47 | 'a' => 'bar', 48 | 0 => 'foo', 49 | 'c' => ['test' => 2], 50 | ] 51 | ``` 52 | 53 | ## sortByKeys 54 | 55 | #### Definition 56 | 57 | ```php 58 | Arr::sortByKeys(array $array, mixed $keys = null, bool $assoc = true): array 59 | ``` 60 | 61 | #### Description 62 | 63 | Sort array of arrays using value specified by key\(s\) 64 | 65 | #### Examples 66 | 67 | ```php 68 | $array = [ 69 | 'a' => ['b' => ['c' => 3]], 70 | 'b' => ['b' => ['c' => -1]], 71 | 'c' => ['b' => ['c' => 0]] 72 | ]; 73 | 74 | Arr::sortByKeys($array, 'b.c') -> 75 | [ 76 | 'c' => ['b' => ['c' => -1]], 77 | 'd' => ['b' => ['c' => 0]], 78 | 'a' => ['b' => ['c' => 3]], 79 | ] 80 | 81 | Arr::sortByKeys($array, 'b.c', false) -> 82 | [ 83 | ['b' => ['c' => -1]], 84 | ['b' => ['c' => 0]], 85 | ['b' => ['c' => 3]], 86 | ] 87 | 88 | Arr::sortByKeys(['a' => 3, 'b' => 1, 'c' => 6]) -> ['b' => 1, 'a' => 3, 'c' => 6] 89 | Arr::sortByKeys(['a' => 3, 'b' => 1, 'c' => 6], null, false) -> [1, 3, 6] 90 | ``` 91 | 92 | ## sortObjects 93 | 94 | #### Definition 95 | 96 | ```php 97 | Arr::sortObjects(array $objects, string $method, ...$args): array 98 | ``` 99 | 100 | #### Description 101 | 102 | Sort array of objects by comparing result of supplied method name 103 | 104 | `$object1->$method(...$args) <=> $object2->$method(...$args)` 105 | 106 | #### Examples 107 | 108 | ```php 109 | $object1 = new class() { 110 | function getValue() { 111 | return 1; 112 | } 113 | }; 114 | $object2 = new class() { 115 | function getValue(bool $reverse = false) { 116 | return $reverse ? 1/2 : 2; 117 | } 118 | }; 119 | $object3 = new class() { 120 | function getValue(bool $reverse = false) { 121 | return $reverse ? 1/3 : 3; 122 | } 123 | }; 124 | 125 | $array = [$object2, $object3, $object1]; 126 | 127 | Arr::sortObjects($array, 'getValue') -> [$object1, $object2, $object3] 128 | Arr::sortObjects($array, 'getValue', true) -> [$object3, $object2, $object1] 129 | ``` 130 | 131 | -------------------------------------------------------------------------------- /docs/object-oriented-methods/general-information.md: -------------------------------------------------------------------------------- 1 | # General information 2 | 3 | ### Object creating 4 | 5 | You can create `ArrObj` by calling 6 | 7 | ```php 8 | new ArrObj(array|ArrayAccess $array = []) 9 | 10 | // Or for easier chaining 11 | Arr::obj(array|ArrayAccess $array = []) 12 | ``` 13 | 14 | ### Chaining 15 | 16 | For chaining just call standard `Arr` methods without first parameter \(array or ArrayAccess object\). 17 | 18 | As a convenience `ArrObj` contains PHPDoc definitions for every available method, so you don't need to guess their parameters. 19 | 20 | Also you can quickly jump to the corresponding `Arr` method by using `@see` tag. 21 | 22 | To obtain array from object just call `getArray()` as the final method in chain. 23 | 24 | ### Examples 25 | 26 | ```php 27 | // Chain setting nested array values 28 | Arr::obj()->set('foo', 'bar')->set('test.[]', 'test')->getArray() -> 29 | [ 30 | 'foo' => 'bar', 31 | 'test' => ['test'] 32 | ] 33 | 34 | // Quickly flatten array of objects grouped by id 35 | Arr::obj([...])->groupObjects('getId')->flattenSingle()->getArray() 36 | ``` 37 | 38 | 39 | 40 | -------------------------------------------------------------------------------- /docs/traversing-array/finding.md: -------------------------------------------------------------------------------- 1 | # Finding 2 | 3 | ## find 4 | 5 | #### Definition 6 | 7 | ```php 8 | Arr::find(array|Iterator|IteratorAggregate $array, callable $condition, string $return = self::FIND_RETURN_VALUE): mixed|mixed[] 9 | ``` 10 | 11 | #### Description 12 | 13 | Find array \(or iterable object\) element\(s\) that match specified condition. 14 | 15 | #### Modes \(`$return` method argument\) 16 | 17 | | Constant name | Description | 18 | | :--- | :--- | 19 | | FIND\_RETURN\_VALUE | Return first value of an array that match find condition | 20 | | FIND\_RETURN\_KEY | Return first key of an array that match find condition | 21 | | FIND\_RETURN\_ALL | Return array of all values \(preserving original keys\) that match find condition | 22 | 23 | #### Examples 24 | 25 | ```php 26 | $array = [ 27 | 'a' => 0, 28 | 'b' => 1, 29 | 3 => 'c', 30 | 4 => 5 31 | ]; 32 | 33 | 34 | Arr::find($array, 'boolval') -> 1 35 | Arr::find($array, function ($element) { 36 | return is_string($element); 37 | }) -> 'c' 38 | 39 | 40 | Arr::find($array, 'boolval', Arr::FIND_RETURN_KEY) -> 'b' 41 | Arr::find($array, function ($element) { 42 | return is_string($element); 43 | }, Arr::FIND_RETURN_KEY) -> 3 44 | 45 | 46 | Arr::find($array, 'boolval', Arr::FIND_RETURN_ALL) -> 47 | [ 48 | 'b' => 1, 49 | 3 => 'c', 50 | 4 => 5 51 | ] 52 | 53 | Arr::find($array, function ($element) { 54 | return is_string($element); 55 | }, Arr::FIND_RETURN_ALL) -> 56 | [ 57 | 3 => 'c', 58 | ] 59 | 60 | Arr::find($array, function ($element) { 61 | return is_number($element); 62 | }, Arr::FIND_RETURN_ALL) -> 63 | [ 64 | 'a' => 0, 65 | 'b' => 1, 66 | 4 => 5 67 | ] 68 | ``` 69 | 70 | -------------------------------------------------------------------------------- /docs/traversing-array/iterating.md: -------------------------------------------------------------------------------- 1 | # Iterating 2 | 3 | ## each 4 | 5 | #### Definition 6 | 7 | ```php 8 | Arr::each(array|Iterator|IteratorAggregate $iterable, callable $callback, int $mode = self::EACH_VALUE): array|Iterator|IteratorAggregate 9 | ``` 10 | 11 | #### Description 12 | 13 | Traverse through array or iterable object and call callback for each element \(ignoring the result\). 14 | 15 | #### Modes 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 29 | 30 | 31 | 32 | 34 | 35 | 36 | 37 | 39 | 40 | 41 | 42 | 50 | 51 | 52 | 53 | 59 | 60 | 61 |
Constant nameDescription
EACH_VALUEIterate using callback in form of function($value) 28 |
EACH_KEY_VALUEIterate using callback in form of function($key, $value) 33 |
EACH_VALUE_KEYIterate using callback in form of function($value, $key) 38 |
EACH_VALUE_KEYS_LIST 43 |

Iterate using callback in form of function($value, $key1, $key2, ...) 44 |
46 |

47 |

Only for array $iterable 48 |

49 |
EACH_KEYS_ARRAY_VALUE 54 |

Iterate using callback in form of function(array $keys, $value) 55 |

56 |


Only for array
$iterable 57 |

58 |
#### Examples 62 | 63 | ```php 64 | $array = [ 65 | 1 => [ 66 | 2 => 'a', 67 | 3 => 'b', 68 | 4 => [ 69 | 5 => 'c', 70 | ], 71 | ], 72 | 'test' => 'd', 73 | ]; 74 | 75 | // Value only - using default EACH_VALUE mode 76 | Arr::each($array, function ($value) { 77 | print_r($value); 78 | // [ 2 => 'a', ...] 79 | // 'd' 80 | }); 81 | 82 | // Key, Value 83 | Arr::each($array, function ($key, $value) { 84 | echo "{$key}: \t\t"; 85 | print_r($value); 86 | // 1: [2 => 'a', ...] 87 | // test: 'd' 88 | }, Arr::EACH_KEY_VALUE); 89 | 90 | // Value, Key 91 | Arr::each($array, function ($value, $key) { 92 | echo "{$key}: \t\t"; 93 | print_r($value); 94 | // 1: [2 => 'a', ...] 95 | // test: 'd' 96 | }, Arr::EACH_VALUE_KEY); 97 | 98 | // Value, Keys list 99 | Arr::each($array, function ($value, ...$keys) { 100 | echo implode('.', $keys) . ': \t\t'; 101 | print_r($value); 102 | // 1.2: 'a' 103 | // 1.3: 'b' 104 | // 1.4.5: 'c' 105 | // test: 'd' 106 | }, Arr::EACH_VALUE_KEYS_LIST); 107 | 108 | 109 | // Keys array, value 110 | Arr::each($array, function (array $keys, $value) { 111 | echo implode('.', $keys) . ': \t\t'; 112 | print_r($value); 113 | // 1.2: 'a' 114 | // 1.3: 'b' 115 | // 1.4.5: 'c' 116 | // test: 'd' 117 | }, Arr::EACH_KEYS_ARRAY_VALUE); 118 | ``` 119 | 120 | -------------------------------------------------------------------------------- /docs/utility-methods/forcearray.md: -------------------------------------------------------------------------------- 1 | # forceArray 2 | 3 | #### Definition 4 | 5 | ```php 6 | Arr::forceArray(mixed $var, int $flag = self::FORCE_ARRAY_ALL): mixed 7 | ``` 8 | 9 | #### Description 10 | 11 | Make variable an array \(according to flag settings\) 12 | 13 | #### Examples 14 | 15 | ```php 16 | Arr::forceArray(0) -> [0] 17 | Arr::forceArray('test') -> ['test'] 18 | 19 | Arr::forceArray(null) -> [null] 20 | Arr::forceArray(null, Arr::FORCE_ARRAY_PRESERVE_NULL) -> null 21 | 22 | 23 | $object = new stdClass(); 24 | 25 | Arr::forceArray($object) -> [$object] 26 | // With this flag all objects remain intact 27 | Arr::forceArray($object, Arr::FORCE_ARRAY_PRESERVE_OBJECTS) -> $object 28 | 29 | 30 | $object = new ArrayObject(); 31 | 32 | Arr::forceArray($object) -> [$object] 33 | // With this flag objects implementing ArrayAccess remain intact 34 | Arr::forceArray($object, Arr::FORCE_ARRAY_PRESERVE_ARRAY_OBJECTS) -> $object 35 | ``` 36 | 37 | -------------------------------------------------------------------------------- /docs/utility-methods/getdepth.md: -------------------------------------------------------------------------------- 1 | # getDepth 2 | 3 | #### Definition 4 | 5 | ```php 6 | Arr::getDepth(array $array): int 7 | ``` 8 | 9 | #### Description 10 | 11 | Get nesting depth of an array 12 | 13 | #### Examples 14 | 15 | ```php 16 | Arr::getDepth([]) -> 1 17 | 18 | Arr::getDepth([1, 2, 3]) -> 1 19 | 20 | Arr::getDepth([1, 2 => [], 3]) -> 2 21 | 22 | Arr::getDepth([ 23 | 1, 24 | 2 => [ 25 | 3 => [ 26 | 4 => [] 27 | ] 28 | ], 29 | 5 => [] 30 | ]) -> 4 31 | ``` 32 | 33 | -------------------------------------------------------------------------------- /docs/utility-methods/getfirstkey.md: -------------------------------------------------------------------------------- 1 | # getFirstKey 2 | 3 | #### Definition 4 | 5 | ```php 6 | Arr::getFirstKey(array $array): int|string|null 7 | ``` 8 | 9 | #### Description 10 | 11 | Get the first key of the given array without affecting the internal array pointer. 12 | 13 | Returns `null` if array is empty. 14 | 15 | #### Examples 16 | 17 | ```php 18 | Arr::getFirstKey(['a' => 1, 'b' => 2, 'c' => 3]) -> 'a' 19 | 20 | Arr::getFirstKey([1, 2, 3]) -> 0 21 | 22 | Arr::getFirstKey([]) -> null 23 | ``` 24 | 25 | -------------------------------------------------------------------------------- /docs/utility-methods/getfirstvalue.md: -------------------------------------------------------------------------------- 1 | # getFirstValue 2 | 3 | #### Definition 4 | 5 | ```php 6 | Arr::getFirstValue(array $array): mixed|null 7 | ``` 8 | 9 | #### Description 10 | 11 | Get the first value of the given array without affecting the internal array pointer. 12 | 13 | Returns `null` if array is empty. 14 | 15 | #### Examples 16 | 17 | ```php 18 | Arr::getFirstValue(['a' => 1, 'b' => 2, 'c' => 3]) -> 1 19 | 20 | Arr::getFirstValue([1, 2, 3, 4, 5]) -> 1 21 | 22 | Arr::getFirstValue([]) -> null 23 | ``` 24 | 25 | -------------------------------------------------------------------------------- /docs/utility-methods/getlastkey.md: -------------------------------------------------------------------------------- 1 | # getLastKey 2 | 3 | #### Definition 4 | 5 | ```php 6 | Arr::getLastKey(array $array): int|string|null 7 | ``` 8 | 9 | #### Description 10 | 11 | Get the last key of the given array without affecting the internal array pointer. 12 | 13 | Returns `null` if array is empty. 14 | 15 | #### Examples 16 | 17 | ```php 18 | Arr::getLastKey(['a' => 1, 'b' => 2, 'c' => 3]) -> 'c' 19 | 20 | Arr::getLastKey([1, 2, 3]) -> 2 21 | 22 | Arr::getLastKey([]) -> null 23 | ``` 24 | 25 | -------------------------------------------------------------------------------- /docs/utility-methods/getlastvalue.md: -------------------------------------------------------------------------------- 1 | # getLastValue 2 | 3 | #### Definition 4 | 5 | ```php 6 | Arr::getLastValue(array $array): mixed|null 7 | ``` 8 | 9 | #### Description 10 | 11 | Get the last value of the given array without affecting the internal array pointer. 12 | 13 | Returns `null` if array is empty. 14 | 15 | #### Examples 16 | 17 | ```php 18 | Arr::getLastValue(['a' => 1, 'b' => 2, 'c' => 3]) -> 3 19 | 20 | Arr::getLastValue([1, 2, 3, 4, 5]) -> 5 21 | 22 | Arr::getLastValue([]) -> null 23 | ``` 24 | 25 | -------------------------------------------------------------------------------- /docs/utility-methods/nth.md: -------------------------------------------------------------------------------- 1 | # nth 2 | 3 | #### Definition 4 | 5 | ```php 6 | Arr::nth(array $array, int $A = 1, int $B = 0): array 7 | ``` 8 | 9 | #### Aliases 10 | 11 | ```php 12 | even(array $array) -> nth($array, 2) 13 | odd(array $array) -> nth($array, 2, 1) 14 | ``` 15 | 16 | #### Description 17 | 18 | Gets array elements with index matching condition $An + $B \(preserving original keys\) 19 | 20 | #### Examples 21 | 22 | ```php 23 | $array = [ 24 | 'a' => 0, 25 | 'b' => 1, 26 | 'c' => 2, 27 | 'd' => 3, 28 | 'e' => 4, 29 | ]; 30 | 31 | Arr::nth($array, 2, 3) -> 32 | [ 33 | 'c' => 2, 34 | 'e' => 4, 35 | ] 36 | 37 | Arr::nth($array, 2) === Arr::even($array) -> 38 | [ 39 | 'a' => 0, 40 | 'c' => 2, 41 | 'e' => 4, 42 | ] 43 | 44 | Arr::nth($array, 2, 1) === Arr::odd($array) -> 45 | [ 46 | 'b' => 1, 47 | 'd' => 3, 48 | ] 49 | ``` 50 | 51 | -------------------------------------------------------------------------------- /docs/utility-methods/pack.md: -------------------------------------------------------------------------------- 1 | # pack 2 | 3 | #### Definition 4 | 5 | ```php 6 | Arr::pack(array $array): array 7 | ``` 8 | 9 | #### Description 10 | 11 | Converts map of keys concatenated by dot and corresponding values to multidimensional array. 12 | 13 | Inverse of [`unpack`](). 14 | 15 | #### Examples 16 | 17 | Let's use result array from [example below](). 18 | 19 | ```php 20 | $array = [ 21 | 'key1.key2.key3.foo' => 'test', 22 | 'key1.key2.key3.bar' => 'test2', 23 | 'key1.abc.0' => 'test3', 24 | 'xyz' => 'test4', 25 | '0' => 'test5', 26 | ]; 27 | 28 | Arr::pack($array) -> 29 | [ 30 | 'key1' => [ 31 | 'key2' => [ 32 | 'key3' => [ 33 | 'foo' => 'test', 34 | 'bar' => 'test2', 35 | ] 36 | ] 37 | 'abc' => ['test3'], 38 | ], 39 | 'xyz' => 'test4', 40 | 'test5' 41 | ] 42 | 43 | // Unpack is inverse operation to pack 44 | $array2 = [ 45 | 'test', 46 | [ 47 | 'foo' => ['bar'], 48 | 'a' => [ 49 | 'b' => 1 50 | ] 51 | ] 52 | ]; 53 | 54 | Arr::unpack(Arr::pack($array2)) === $array2 -> true 55 | ``` 56 | 57 | -------------------------------------------------------------------------------- /docs/utility-methods/random.md: -------------------------------------------------------------------------------- 1 | # random 2 | 3 | #### Definition 4 | 5 | ```php 6 | Arr::random(array $array, int $count = 1): mixed 7 | ``` 8 | 9 | #### Description 10 | 11 | Get random array value\(s\) 12 | 13 | #### Examples 14 | 15 | ```php 16 | $array = [ 17 | 'a' => 1, 18 | 'b' => 2, 19 | 'c' => 3, 20 | 'd' => 4, 21 | 'e' => 5 22 | ]; 23 | 24 | Arr::random($array) -> 5 25 | Arr::random($array) -> 1 26 | Arr::random($array) -> 3 27 | Arr::random($array) -> 2 28 | 29 | Arr::random($array, 2) -> ['d' => 4, 'a' => 1] 30 | Arr::random($array, 2) -> ['b' => 2, 'e' => 5] 31 | Arr::random($array, 2) -> ['c' => 3, 'b' => 2] 32 | ``` 33 | 34 | -------------------------------------------------------------------------------- /docs/utility-methods/shuffle.md: -------------------------------------------------------------------------------- 1 | # shuffle 2 | 3 | #### Definition 4 | 5 | ```php 6 | Arr::shuffle(array $array): array 7 | ``` 8 | 9 | #### Description 10 | 11 | Shuffle array preserving keys and returning new shuffled array 12 | 13 | #### Examples 14 | 15 | ```php 16 | $array = [ 17 | 'a' => 1, 18 | 'b' => 2, 19 | 'c' => 3, 20 | 'd' => 4, 21 | 'e' => 5, 22 | ]; 23 | 24 | Arr::shuffle($array) -> 25 | [ 26 | 'e' => 5, 27 | 'a' => 1, 28 | 'c' => 3, 29 | 'b' => 2, 30 | 'd' => 4, 31 | ] 32 | 33 | Arr::shuffle($array) -> 34 | [ 35 | 'a' => 1, 36 | 'e' => 5, 37 | 'b' => 2, 38 | 'd' => 4, 39 | 'c' => 3, 40 | ] 41 | ``` 42 | 43 | -------------------------------------------------------------------------------- /docs/utility-methods/unpack.md: -------------------------------------------------------------------------------- 1 | # unpack 2 | 3 | #### Definition 4 | 5 | ```php 6 | Arr::unpack(array $array, int $mode = Arr::UNPACK_ALL): array 7 | ``` 8 | 9 | #### Description 10 | 11 | Converts multidimensional array to map of keys concatenated by dot and corresponding values. 12 | 13 | Inverse of [`pack`](). 14 | 15 | #### Modes 16 | 17 | | Mode | Description | 18 | | :--- | :--- | 19 | | `Arr::UNPACK_ALL` | Every array will be unpacked | 20 | | `Arr::UNPACK_PRESERVE_LIST_ARRAY` | Preserve arrays with highest nesting level \(if they are not associative\) as element values instead of unpacking them | 21 | | `Arr::UNPACK_PRESERVE_ASSOC_ARRAY` | Preserve arrays with highest nesting level \(if they are associative\) as element values instead of unpacking them | 22 | | `Arr::UNPACK_PRESERVE_ARRAY` | Preserve all arrays with highest nesting level as element values instead of unpacking them | 23 | 24 | #### Examples 25 | 26 | ```php 27 | $array = [ 28 | 'key1' => [ 29 | 'key2' => [ 30 | 'key3' => [ 31 | 'foo' => 'test', 32 | 'bar' => 'test2', 33 | ] 34 | ] 35 | 'abc' => ['test3'], 36 | ], 37 | 'xyz' => 'test4', 38 | 'test5' 39 | ]; 40 | 41 | // Equal to Arr::unpack($array, Arr::UNPACK_ALL) 42 | Arr::unpack($array) -> 43 | [ 44 | 'key1.key2.key3.foo' => 'test', 45 | 'key1.key2.key3.bar' => 'test2', 46 | 'key1.abc.0' => 'test3', 47 | 'xyz' => 'test4', 48 | '0' => 'test5', 49 | ] 50 | 51 | Arr::unpack($array, Arr::UNPACK_PRESERVE_LIST_ARRAY) -> 52 | [ 53 | 'key1.key2.key3.foo' => 'test', 54 | 'key1.key2.key3.bar' => 'test2', 55 | // Preserve list array as value 56 | 'key1.abc' => ['test3'], 57 | 'xyz' => 'test4', 58 | '0' => 'test5', 59 | ] 60 | 61 | Arr::unpack($array, Arr::UNPACK_PRESERVE_ASSOC_ARRAY) -> 62 | [ 63 | // Preserve assoc array as value 64 | 'key1.key2.key3' => [ 65 | 'foo' => 'test', 66 | 'bar' => 'test2', 67 | ], 68 | 'key1.abc.0' => 'test3', 69 | 'xyz' => 'test4', 70 | '0' => 'test5', 71 | ] 72 | 73 | Arr::unpack($array, Arr::UNPACK_PRESERVE_ARRAY) -> 74 | [ 75 | // Preserve assoc array as value 76 | 'key1.key2.key3' => [ 77 | 'foo' => 'test', 78 | 'bar' => 'test2', 79 | ], 80 | // Preserve list array as value 81 | 'key1.abc' => ['test3'], 82 | 'xyz' => 'test4', 83 | '0' => 'test5', 84 | ] 85 | ``` 86 | 87 | -------------------------------------------------------------------------------- /docs/utility-methods/untitled.md: -------------------------------------------------------------------------------- 1 | # createMulti 2 | 3 | #### Definition 4 | 5 | ```php 6 | Arr::createMulti(array $keys, ?array $values = null): array 7 | ``` 8 | 9 | #### Description 10 | 11 | Create multidimensional array using either first param as config of keys and values or separate keys and values arrays 12 | 13 | #### Examples 14 | 15 | ```php 16 | Arr::createMulti([ 17 | 'test.[]' => '123', 18 | 'test.test2.test3' => 'abc', 19 | 'test.test2.[]' => 567, 20 | 'test.[].1' => 'def', 21 | ]) -> 22 | [ 23 | 'test' => [ 24 | '123', 25 | 'test2' => [ 26 | 'test3' => 'abc', 27 | 567 28 | ], 29 | [ 30 | 1 => 'def' 31 | ], 32 | ] 33 | ] 34 | 35 | Arr::createMulti([ 36 | ['test', '[]'], 37 | ['test', 'test2', 'test3'], 38 | ['test', 'test2', '[]'], 39 | ['test', '[]', 1], 40 | ], [ 41 | '123', 42 | 'abc', 43 | 567, 44 | 'def', 45 | ]) -> 46 | [ 47 | 'test' => [ 48 | '123', 49 | 'test2' => [ 50 | 'test3' => 'abc', 51 | 567 52 | ], 53 | [ 54 | 1 => 'def' 55 | ], 56 | ] 57 | ] 58 | 59 | // In case of empty keys argument simply return new empty array 60 | Arr::createMulti([]) -> [] 61 | ``` 62 | 63 | -------------------------------------------------------------------------------- /docs/validating-array/check.md: -------------------------------------------------------------------------------- 1 | # check 2 | 3 | #### Definition 4 | 5 | {% code title="" %} 6 | ```php 7 | Arr::check(array $array, mixed|callable $condition, int $flag = 0): bool 8 | ``` 9 | {% endcode %} 10 | 11 | #### Description 12 | 13 | Check if some or every array element meets specified condition. 14 | 15 | If `CHECK_SOME` flag is NOT present then every array element must meet specified condition in order to pass check. 16 | 17 | #### Condition 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 30 | 41 | 42 | 43 | 45 | 52 | 53 | 54 |
$condition typeDescription
callable 29 | 31 |

Callable should return truthy or falsy value (while using CHECK_STRICT flag, 32 | return values other than true are treated as false).

33 |

34 |

Callable is supplied with either only element value (function($value)) 35 | or pair of element value and key (function($value, $key)) 36 | as arguments. 37 |
Arguments amount depend on callable definition and is dynamically 38 | resolved using reflection (defaults 39 | to 2 - value and key)

40 |
mixed 44 | 46 |

If condition type is different than callable then every 47 | array element is compared against it value.

48 |

49 |

$value == $condition by default

50 |

$value === $conditionif CHECK_STRICT flag is enabled

51 |
#### Flags 55 | 56 | Can be used as stand alone \(i.e.`Arr::CHECK_STRICT`\) as well as in conjunction \(i.e. `Arr::CHECK_STRICT | Arr::CHECK_SOME`\) 57 | 58 | {% hint style="info" %} 59 | `$flag` argument used to be a boolean parameter called `$strict` 60 | 61 | But do not worry, it it is fully backward compatible due to in-flight type conversion from `bool` to `int` 62 | {% endhint %} 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 75 | 85 | 86 | 87 | 89 | 97 | 98 | 99 |
Constant nameDescription
CHECK_STRICT 74 | 76 |

In case condition is callable check if it result is 77 | exactly true 78 |

79 |

80 |
If condition is not callable, then check if array element 81 | is equal to it both by value and type

82 |

83 |

See Condition section for more info

84 |
CHECK_SOME 88 | 90 |

Check will return true on first array element that match specified condition or 91 | false if none of them matches it.

92 |

93 |

By default check method will return true only if 94 | ALL of array elements meet specified condition 95 |

96 |
#### Examples 100 | 101 | ```php 102 | $array = [1, '1', true]; 103 | 104 | // Every array element is EQUAL to 1 ($value == '1') 105 | Arr::check($array, '1') -> true 106 | 107 | // Only one array element is the SAME as 1 ($value === '1') which is not sufficient 108 | Arr::check($array, '1', Arr::CHECK_STRICT) -> false 109 | 110 | // When CHECK_SOME flag is present, one element is sufficient to pass check 111 | Arr::check($array, '1', Arr::CHECK_STRICT | Arr::CHECK_SOME) -> true 112 | 113 | // You can also use built-in functions to validate whole array 114 | Arr::check($array, 'is_int') -> false 115 | Arr::check($array, 'is_string') -> false 116 | 117 | // When CHECK_SOME flag is present only one element need to meet specified condition 118 | Arr::check($array, 'is_int', Arr::CHECK_SOME) -> true 119 | Arr::check($array, 'is_string', Arr::CHECK_SOME) -> true 120 | 121 | // Every value of array is truthy 122 | Arr::check($array, function ($value) { return $value; }) -> true 123 | // Above check can be simplified to 124 | Arr::check($array, true) -> true 125 | // Or even shorter 126 | Arr::check($array, 1) -> true 127 | 128 | // When CHECK_STRICT flag is present, check will fail for callback return values other true 129 | Arr::check($array, function ($value) { return $value; }, Arr::CHECK_STRICT) -> false 130 | // But when callback is written as follows check will pass 131 | Arr::check($array, function ($value) { return boolval($value); }, Arr::CHECK_STRICT) -> true 132 | // Above check will pass if we add CHECK_SOME flag cause of of the elements is exactly true 133 | Arr::check($array, function ($value) { return $value; }, Arr::CHECK_STRICT | Arr::CHECK_SOME) -> true 134 | 135 | 136 | // Callback function arguments count is automatically detected 137 | Arr::check($array, function ($value, $key) { return $value > $key; }) -> false 138 | // First array element 1 is greater than its key 0 139 | Arr::check($array, function ($value, $key) { return $value > $key; }, Arr::CHECK_SOME) -> true 140 | ``` 141 | 142 | -------------------------------------------------------------------------------- /docs/validating-array/haskeys.md: -------------------------------------------------------------------------------- 1 | # hasKeys 2 | 3 | #### Definition 4 | 5 | ```php 6 | Arr::hasKeys(array $array, mixed $keys, bool $strict = false): bool 7 | ``` 8 | 9 | #### Description 10 | 11 | Check if array has specified keys \( all required, when `$strict` is `true`\). 12 | 13 | #### Examples 14 | 15 | ```php 16 | $array = ['key1' => 1, 'key2' => 2, 'key3' => 3]; 17 | 18 | Arr::hasKeys($array, ['key2', 'key3']) -> true 19 | 20 | Arr::hasKeys($array, 'key1.key2') -> true 21 | 22 | Arr::hasKeys($array, ['test', 'key1']) -> true 23 | 24 | Arr::hasKeys($array, ['test', 'key1'], true) -> false 25 | 26 | Arr::hasKeys($array, 'test') -> false 27 | ``` 28 | 29 | -------------------------------------------------------------------------------- /docs/validating-array/isarrayofarrays.md: -------------------------------------------------------------------------------- 1 | # isArrayOfArrays 2 | 3 | #### Definition 4 | 5 | ```php 6 | Arr::isArrayOfArrays(array $array): bool 7 | ``` 8 | 9 | #### Description 10 | 11 | Check if every array element is array 12 | 13 | #### Examples 14 | 15 | ```php 16 | Arr::isArrayOfArrays([]) -> false 17 | 18 | Arr::isArrayOfArrays([[], []]) -> true 19 | 20 | Arr::isArrayOfArrays([1, 2 => []]) -> false 21 | ``` 22 | 23 | -------------------------------------------------------------------------------- /docs/validating-array/isassoc.md: -------------------------------------------------------------------------------- 1 | # isAssoc 2 | 3 | #### Definition 4 | 5 | ```php 6 | Arr::isAssoc(array $array, bool $strict = false): bool 7 | ``` 8 | 9 | #### Description 10 | 11 | Check if array is associative 12 | 13 | #### Examples 14 | 15 | ```php 16 | $array = ['a' => 1, 'b' => 3, 1 => 'd', 'c']; 17 | 18 | Arr::isAssoc($array) -> true 19 | Arr::isAssoc($array, true) -> true 20 | 21 | 22 | $array = [1 => 1, 2 => 2, 3 => 3]; 23 | 24 | // There are no string keys 25 | Arr::isAssoc($array) -> false 26 | 27 | // However indexes are not automatically generated (starting from 0 up) 28 | Arr::isAssoc($array, true) -> true 29 | 30 | // In this case keys are automatically generated 31 | Arr::isAssoc([1, 2, 3], true) -> false 32 | 33 | // Which is equal to this 34 | Arr::isAssoc([0 => 1, 1 => 2, 2 => 3], true) -> false 35 | ``` 36 | 37 | -------------------------------------------------------------------------------- /docs/validating-array/isempty.md: -------------------------------------------------------------------------------- 1 | # isEmpty 2 | 3 | #### Definition 4 | 5 | ```php 6 | Arr::isEmpty(mixed $array): bool 7 | ``` 8 | 9 | #### Description 10 | 11 | Recursively check if all of array values match empty condition. 12 | 13 | #### Examples 14 | 15 | ```php 16 | Arr::isEmpty(null) -> true 17 | 18 | Arr::isEmpty([]) -> true 19 | 20 | Arr::isEmpty([0 => [0], [], null, [false]) -> true 21 | Arr::isEmpty([0 => [0 => 'a'], [], null, [false]]) -> false 22 | ``` 23 | 24 | -------------------------------------------------------------------------------- /docs/validating-array/isnested.md: -------------------------------------------------------------------------------- 1 | # isNested 2 | 3 | #### Definition 4 | 5 | ```php 6 | Arr::isNested(array $array): bool 7 | ``` 8 | 9 | #### Description 10 | 11 | Check if any element of an array is also an array 12 | 13 | #### Examples 14 | 15 | ```php 16 | Arr::isNested([]) -> false 17 | 18 | Arr::isNested([1, 2, 3]) -> false 19 | 20 | Arr::isNested([1, 2 => [], 3]) -> true 21 | 22 | Arr::isNested([1, 2 => [[[]]], 3 => []]) -> true 23 | ``` 24 | 25 | -------------------------------------------------------------------------------- /docs/validating-array/isnumeric.md: -------------------------------------------------------------------------------- 1 | # isNumeric 2 | 3 | #### Definition 4 | 5 | ```php 6 | Arr::isNumeric(array $array): bool 7 | ``` 8 | 9 | #### Description 10 | 11 | Check if array contain only numeric values 12 | 13 | #### Examples 14 | 15 | ```php 16 | Arr::isNumeric([1, '2', '3e10', 5.0002]) -> true 17 | 18 | Arr::isNumeric([1, '2', '3e10', 5.0002, 'a']) -> false 19 | ``` 20 | 21 | -------------------------------------------------------------------------------- /docs/validating-array/isunique.md: -------------------------------------------------------------------------------- 1 | # isUnique 2 | 3 | #### Definition 4 | 5 | ```php 6 | Arr::isUnique(array $array, bool $strict = false): bool 7 | ``` 8 | 9 | #### Description 10 | 11 | Check if array values are unique 12 | 13 | #### Examples 14 | 15 | ```php 16 | // Without strict flag 1 is equal to '1' 17 | Arr::isUnique([1, '1', true]) -> false 18 | 19 | Arr::isUnique([1, '1', true], true) -> true 20 | ``` 21 | 22 | -------------------------------------------------------------------------------- /phpunit.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | ./tests 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | ./src 14 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /src/Arr.php: -------------------------------------------------------------------------------- 1 | In case condition is callable check if it result is exactly true

100 | *

If condition is not callable, then check if array element is equal to it both by value and type

101 | */ 102 | const CHECK_STRICT = 1; 103 | 104 | /** 105 | * Check will return true on first array element that match specified condition 106 | */ 107 | const CHECK_SOME = 2; 108 | 109 | private const AUTO_INDEX_KEY = '[]'; 110 | private const KEY_SEPARATOR = '.'; 111 | 112 | /*--------------------------------------------------------------------------------------*\ 113 | | Common | 114 | | ****************************************************************************** | 115 | | Basic operations used by other methods | 116 | \*--------------------------------------------------------------------------------------*/ 117 | 118 | 119 | /** 120 | * Convert variable into normalized array of keys
121 | *
122 | * Transforms 'key1.key2.key3' strings into ['key1','key2','key3']
123 | *
124 | * When array is supplied, this function preserve only not empty strings and integers
125 | *
 126 |      * ['', 'test', 5.5, null, 0] -> ['test', 0]
 127 |      * 
128 | * 129 | * @param mixed $keys 130 | * @return array 131 | */ 132 | public static function getKeysArray($keys): array 133 | { 134 | if (is_string($keys)) { 135 | return empty($keys) ? [] : explode(self::KEY_SEPARATOR, $keys); 136 | } 137 | return is_null($keys) ? [] : array_filter(array_values(self::forceArray($keys)), function ($value) { 138 | return $value !== null && $value !== '' && (is_string($value) || is_int($value)); 139 | }); 140 | } 141 | 142 | /** 143 | * Check if specified (nested) key(s) exists in array 144 | * 145 | * @param array $array 146 | * @param mixed $keys Keys needed to access desired array element (for possible formats see getKeysArray method) 147 | * @return bool 148 | * @see Arr::getKeysArray() 149 | */ 150 | public static function has(array $array, $keys): bool 151 | { 152 | $keysArray = self::getKeysArray($keys); 153 | 154 | if (empty($keysArray)) { 155 | return false; 156 | } 157 | 158 | $tmp = $array; 159 | 160 | foreach ($keysArray as $key) { 161 | if (!is_array($tmp) || !array_key_exists($key, $tmp)) { 162 | return false; 163 | } 164 | $tmp = $tmp[$key]; 165 | } 166 | 167 | return true; 168 | } 169 | 170 | /** 171 | * Check if array has list of specified keys 172 | * 173 | * @param array $array 174 | * @param mixed $keys Keys needed to access desired array element (for possible formats see getKeysArray method) 175 | * @param bool $strict If array must have all of specified keys 176 | * @return bool 177 | * @see Arr::getKeysArray() 178 | */ 179 | public static function hasKeys(array $array, $keys, bool $strict = false): bool 180 | { 181 | foreach (self::getKeysArray($keys) as $key) { 182 | if (array_key_exists($key, $array) && !$strict) { 183 | return true; 184 | } elseif (!array_key_exists($key, $array) && $strict) { 185 | return false; 186 | } 187 | } 188 | return $strict ? true : false; 189 | } 190 | 191 | /** 192 | * Alias of Arr::getNestedElement 193 | * 194 | * @param array|ArrayAccess $array Array or object implementing array access to get element from 195 | * @param mixed $keys Keys needed to access desired array element (for possible formats see getKeysArray method) 196 | * @param mixed $default Default value if element was not found 197 | * @return null|mixed 198 | * @see Arr::getNestedElement() 199 | */ 200 | public static function get($array, $keys, $default = null) 201 | { 202 | return self::getNestedElement($array, $keys, $default); 203 | } 204 | 205 | /** 206 | * Get nested element of an array or object implementing array access 207 | * 208 | * @param array|ArrayAccess $array Array or object implementing array access to get element from 209 | * @param mixed $keys Keys needed to access desired array element (for possible formats see getKeysArray method) 210 | * @param mixed $default Default value if element was not found 211 | * @return null|mixed 212 | * @see Arr::getKeysArray() 213 | */ 214 | public static function getNestedElement($array, $keys, $default = null) 215 | { 216 | $keys = self::getKeysArray($keys); 217 | foreach ($keys as $key) { 218 | if (!is_array($array) && !$array instanceof ArrayAccess) { 219 | return $default; 220 | } 221 | if (($array instanceof ArrayAccess && $array->offsetExists($key)) || array_key_exists($key, $array)) { 222 | $array = $array[$key]; 223 | } else { 224 | return $default; 225 | } 226 | } 227 | return $array; 228 | } 229 | 230 | /** 231 | * Alias of Arr::setNestedElement 232 | * 233 | * @param array|ArrayAccess $array Array or object implementing array access to set element on 234 | * @param mixed $keys Keys needed to access desired array element (for possible formats see getKeysArray method) 235 | * @param mixed $value Value to set 236 | * @return array|ArrayAccess Copy of an array with element set 237 | * @see Arr::setNestedElement() 238 | */ 239 | public static function set($array, $keys, $value) 240 | { 241 | return self::setNestedElement($array, $keys, $value); 242 | } 243 | 244 | /** 245 | * Set array element specified by keys to the desired value (create missing keys if necessary) 246 | * 247 | * @param array|ArrayAccess $array Array or object implementing array access to set element on 248 | * @param mixed $keys Keys needed to access desired array element (for possible formats see getKeysArray method) 249 | * @param mixed $value Value to set 250 | * @return array|ArrayAccess Copy of an array with element set 251 | * @see Arr::getKeysArray() 252 | */ 253 | public static function setNestedElement($array, $keys, $value) 254 | { 255 | $result = $array; 256 | $keysArray = self::getKeysArray($keys); 257 | 258 | // If no keys specified then preserve array 259 | if (empty($keysArray)) { 260 | return $result; 261 | } 262 | 263 | $tmp = &$result; 264 | 265 | while (count($keysArray) > 0) { 266 | $key = array_shift($keysArray); 267 | if (!is_array($tmp)) { 268 | $tmp = []; 269 | } 270 | if ($key === self::AUTO_INDEX_KEY) { 271 | $tmp[] = null; 272 | end($tmp); 273 | $key = key($tmp); 274 | } 275 | $tmp = &$tmp[$key]; 276 | } 277 | $tmp = $value; 278 | 279 | return $result; 280 | } 281 | 282 | /** 283 | * Remove element inside array at path specified by keys 284 | * 285 | * @param array $array 286 | * @param mixed $keys Keys needed to access desired array element (for possible formats see getKeysArray method) 287 | * @return array 288 | * @see Arr::getKeysArray() 289 | */ 290 | public static function remove(array $array, $keys): array 291 | { 292 | $result = $array; 293 | $keysArray = self::getKeysArray($keys); 294 | 295 | $tmp = &$result; 296 | 297 | while (count($keysArray) > 1) { 298 | $key = array_shift($keysArray); 299 | if (!is_array($tmp) || !array_key_exists($key, $tmp)) { 300 | return $result; 301 | } 302 | 303 | $tmp = &$tmp[$key]; 304 | } 305 | $key = array_shift($keysArray); 306 | unset($tmp[$key]); 307 | 308 | return $result; 309 | } 310 | 311 | /** 312 | * Converts map of keys concatenated by dot and corresponding values to multidimensional array 313 | * 314 | * @param array $array 315 | * @return array 316 | */ 317 | public static function pack(array $array): array 318 | { 319 | $result = []; 320 | 321 | foreach ($array as $key => $value) { 322 | $result = self::setNestedElement($result, $key, $value); 323 | } 324 | 325 | return $result; 326 | } 327 | 328 | /** 329 | * Converts multidimensional array to map of keys concatenated by dot and corresponding values 330 | * 331 | * @param array $array 332 | * @param int $mode Modify behaviour of unpack (see description of Arr::UNPACK_ constants) 333 | * @return array 334 | */ 335 | public static function unpack(array $array, int $mode = self::UNPACK_ALL): array 336 | { 337 | return self::_unpack($array, $mode); 338 | } 339 | 340 | /** 341 | * Check if every element of an array meets specified condition 342 | * 343 | * @param array $array 344 | * @param mixed $condition

Either callable performing check or a value which every array element will be compared to.

345 | *

Callable is supplied with either only element value or pair of element value and key. Arguments amount depends on callable definition and is dynamically resolved using reflection (defaults to 2 - value and key)

346 | * @param int $flag

[optional]

347 | *

Determines how condition is processed (see Arr::CHECK_* constants for more info)

348 | * 352 | * @return bool 353 | * @see Arr::CHECK_STRICT 354 | * @see Arr::CHECK_SOME 355 | * @see ReflectionMethod::getNumberOfParameters() 356 | * @see ReflectionFunction::getNumberOfParameters() 357 | */ 358 | public static function check(array $array, $condition, int $flag = 0): bool 359 | { 360 | if (is_callable($condition)) { 361 | try { 362 | $reflection = is_array($condition) ? 363 | new ReflectionMethod($condition[0], $condition[1]) : 364 | new ReflectionMethod($condition); 365 | 366 | $paramsCount = $reflection->getNumberOfParameters(); 367 | } catch (Throwable $e) { 368 | try { 369 | $reflection = new ReflectionFunction($condition); 370 | $paramsCount = $reflection->getNumberOfParameters(); 371 | } catch (Throwable $exception) { // @codeCoverageIgnore 372 | $paramsCount = 2; // @codeCoverageIgnore 373 | } 374 | } 375 | } 376 | 377 | $checkStrict = $flag & self::CHECK_STRICT; 378 | $checkSome = $flag & self::CHECK_SOME; 379 | 380 | foreach ($array as $key => $value) { 381 | if (is_callable($condition)) { 382 | $result = $paramsCount == 1 ? call_user_func($condition, $value) : call_user_func($condition, $value, $key); 383 | 384 | if ($checkStrict ? $result === true : $result) { 385 | if ($checkSome) { 386 | return true; 387 | } 388 | } else { 389 | if (!$checkSome) { 390 | return false; 391 | } 392 | } 393 | } else { 394 | if ($checkStrict ? $value === $condition : $value == $condition) { 395 | if ($checkSome) { 396 | return true; 397 | } 398 | } else { 399 | if (!$checkSome) { 400 | return false; 401 | } 402 | } 403 | } 404 | } 405 | 406 | return $checkSome ? false : true; 407 | } 408 | 409 | private static function _unpack(array $array, int $mode = self::UNPACK_ALL, array $keys = []): array 410 | { 411 | $result = []; 412 | 413 | foreach ($array as $key => $value) { 414 | 415 | if (is_array($value) && !( 416 | // Check if value IS NOT a subject for preserve mode 417 | !self::isNested($value) && // Preserve mode only work for highest depth elements 418 | ( 419 | ($mode === self::UNPACK_PRESERVE_LIST_ARRAY && !self::isAssoc($value, true)) || 420 | ($mode === self::UNPACK_PRESERVE_ASSOC_ARRAY && self::isAssoc($value, true)) || 421 | $mode === self::UNPACK_PRESERVE_ARRAY 422 | ) 423 | )) { 424 | $keys[] = $key; 425 | $result += self::_unpack($value, $mode, $keys); 426 | array_pop($keys); 427 | } else { 428 | $result[implode(self::KEY_SEPARATOR, array_merge($keys, [$key]))] = $value; 429 | } 430 | } 431 | 432 | return $result; 433 | } 434 | 435 | /*--------------------------------------------------------------------------------------*\ 436 | | Validation | 437 | | ****************************************************************************** | 438 | | Flexible check method and various specific checks | 439 | \*--------------------------------------------------------------------------------------*/ 440 | 441 | /** 442 | * Recursively check if all of array values match empty condition 443 | * 444 | * @param array|ArrayAccess $array 445 | * @return boolean 446 | */ 447 | public static function isEmpty($array): bool 448 | { 449 | if (is_array($array)) { 450 | foreach ($array as $v) { 451 | if (!self::isEmpty($v)) { 452 | return false; 453 | } 454 | } 455 | } elseif (!empty($array)) { 456 | return false; 457 | } 458 | 459 | return true; 460 | } 461 | 462 | /** 463 | * Check if array is associative 464 | * 465 | * @param array $array 466 | * @param bool $strict 467 | *

If false then this function will match any array that doesn't contain integer keys.

468 | *

If true then this function match only arrays with sequence of integers starting from zero (range from 0 to elements_number - 1) as keys.

469 | * 470 | * @return boolean 471 | */ 472 | public static function isAssoc(array $array, bool $strict = false): bool 473 | { 474 | if (empty($array)) { 475 | return false; 476 | } 477 | 478 | if ($strict) { 479 | return array_keys($array) !== range(0, count($array) - 1); 480 | } else { 481 | foreach (array_keys($array) as $key) { 482 | if (!is_int($key)) { 483 | return true; 484 | } 485 | } 486 | return false; 487 | } 488 | } 489 | 490 | /** 491 | * Check if array contain only numeric values 492 | * 493 | * @param array $array 494 | * @return bool 495 | */ 496 | public static function isNumeric(array $array): bool 497 | { 498 | return self::check($array, 'is_numeric'); 499 | } 500 | 501 | /** 502 | * Check if array values are unique 503 | * 504 | * @param array $array 505 | * @param bool $strict If it should also compare type 506 | * @return bool 507 | */ 508 | public static function isUnique(array $array, bool $strict = false): bool 509 | { 510 | if ($strict) { 511 | foreach ($array as $key => $value) { 512 | $keys = array_keys($array, $value, true); 513 | if (count($keys) > 1 || $keys[0] !== $key) { 514 | return false; 515 | } 516 | } 517 | return true; 518 | } 519 | return array_unique(array_values($array), SORT_REGULAR) === array_values($array); 520 | } 521 | 522 | /** 523 | * Check if any element of an array is also an array 524 | * 525 | * @param array $array 526 | * @return bool 527 | */ 528 | public static function isNested(array $array): bool 529 | { 530 | foreach ($array as $element) { 531 | if (is_array($element)) { 532 | return true; 533 | } 534 | } 535 | 536 | return false; 537 | } 538 | 539 | /** 540 | * Check if every element of an array is array 541 | * 542 | * @param array $array 543 | * @return bool 544 | */ 545 | public static function isArrayOfArrays(array $array): bool 546 | { 547 | // If empty array 548 | if (count($array) === 0) { 549 | return false; 550 | } 551 | foreach ($array as $element) { 552 | if (!is_array($element)) { 553 | return false; 554 | } 555 | } 556 | return true; 557 | } 558 | 559 | /*--------------------------------------------------------------------------------------*\ 560 | | Manipulation | 561 | | ****************************************************************************** | 562 | | Well known methods (like map, filter, group etc.) in 2 variants: regular and objects | 563 | \*--------------------------------------------------------------------------------------*/ 564 | 565 | /** 566 | * Applies a callback to the elements of given array 567 | * 568 | * @param array|callable $array 569 | * @param callable|array $callback Callback to run for each element of array 570 | * @param int $mode Determines callback arguments order and format
571 | *
572 | * MAP_ARRAY_KEY_VALUE -> callback($key, $value)
573 | * MAP_ARRAY_VALUE_KEYS_LIST -> callback($value, $key1, $key2, ...)
574 | * MAP_ARRAY_KEYS_ARRAY_VALUE -> callback(array $keys, $value) 575 | * MAP_ARRAY_VALUE_KEY -> callback($value, $key) 576 | * @return array 577 | */ 578 | public static function map($array, $callback, int $mode = self::MAP_ARRAY_KEY_VALUE): array 579 | { 580 | // If has old arguments order then swap and issue warning 581 | if (is_callable($array) && is_array($callback)) { 582 | $tmp = $array; 583 | $array = $callback; 584 | $callback = $tmp; 585 | trigger_error('Supplying callback as first argument to Arr::map method is deprecated and will trigger error in next major release. Please use new syntax -> Arr::map(array $array, callback $callback, int $mode)', E_USER_DEPRECATED); 586 | } 587 | $result = []; 588 | 589 | switch ($mode) { 590 | case self::MAP_ARRAY_KEY_VALUE: 591 | foreach ($array as $key => $value) { 592 | $result[$key] = $callback($key, $value); 593 | } 594 | break; 595 | case self::MAP_ARRAY_VALUE_KEY: 596 | foreach ($array as $key => $value) { 597 | $result[$key] = $callback($value, $key); 598 | } 599 | break; 600 | case self::MAP_ARRAY_VALUE_KEYS_LIST: 601 | foreach (self::unpack($array) as $dotKeys => $value) { 602 | $keys = self::getKeysArray($dotKeys); 603 | $result = self::setNestedElement($result, $keys, $callback($value, ...$keys)); 604 | } 605 | break; 606 | case self::MAP_ARRAY_KEYS_ARRAY_VALUE: 607 | foreach (self::unpack($array) as $dotKeys => $value) { 608 | $keys = self::getKeysArray($dotKeys); 609 | $result = self::setNestedElement($result, $keys, $callback($keys, $value)); 610 | } 611 | break; 612 | } 613 | 614 | return $result; 615 | } 616 | 617 | /** 618 | * Map array of object to values returned from objects method 619 | * 620 | * This method leaves values other than objects intact 621 | * 622 | * @param array $objects Array of objects 623 | * @param string $method Object method name 624 | * @param mixed ...$args Method arguments 625 | * @return array 626 | */ 627 | public static function mapObjects(array $objects, string $method, ...$args): array 628 | { 629 | $return = []; 630 | 631 | foreach ($objects as $key => $value) { 632 | if (is_object($value)) { 633 | $return[$key] = $value->$method(...$args); 634 | } else { 635 | $return[$key] = $value; 636 | } 637 | } 638 | 639 | return $return; 640 | } 641 | 642 | /** 643 | * Traverse through array or iterable object and call callback for each element (ignoring the result).
644 | *
645 | * Warning: For EACH_VALUE_KEYS_LIST and EACH_KEYS_ARRAY_VALUE modes $iterable MUST be an array. 646 | * 647 | * @param array|Iterator|IteratorAggregate $iterable Usually array, but can be an iterable object. 648 | * @param callable $callback Callback function for each element of an iterable 649 | * @param int $mode What parameters and in which order should $callback receive 650 | * @return array|Iterator|IteratorAggregate Return unchanged input for chaining 651 | */ 652 | public static function each($iterable, callable $callback, int $mode = self::EACH_VALUE) 653 | { 654 | switch ($mode) { 655 | case self::EACH_KEY_VALUE: 656 | foreach ($iterable as $key => $value) { 657 | $callback($key, $value); 658 | } 659 | break; 660 | case self::EACH_VALUE_KEY: 661 | foreach ($iterable as $key => $value) { 662 | $callback($value, $key); 663 | } 664 | break; 665 | case self::EACH_VALUE_KEYS_LIST: 666 | foreach (self::unpack($iterable) as $dotKeys => $value) { 667 | $keys = self::getKeysArray($dotKeys); 668 | $callback($value, ...$keys); 669 | } 670 | break; 671 | case self::EACH_KEYS_ARRAY_VALUE: 672 | foreach (self::unpack($iterable) as $dotKeys => $value) { 673 | $keys = self::getKeysArray($dotKeys); 674 | $callback($keys, $value); 675 | } 676 | break; 677 | case self::EACH_VALUE: 678 | default: 679 | foreach ($iterable as $value) { 680 | $callback($value); 681 | } 682 | break; 683 | } 684 | 685 | return $iterable; 686 | } 687 | 688 | /** 689 | * Filter array values by preserving only those which keys are present in array obtained from $keys variable 690 | * 691 | * @param array $array 692 | * @param mixed $keys Keys needed to access desired array element (for possible formats see getKeysArray method) 693 | * @param bool $exclude If values matching $keys should be excluded from returned array 694 | * @return array 695 | * @see Arr::getKeysArray() 696 | */ 697 | public static function filterByKeys(array $array, $keys, bool $exclude = false): array 698 | { 699 | if (is_null($keys)) { 700 | return $array; 701 | } 702 | $keysArray = self::getKeysArray($keys); 703 | if (empty($keysArray)) { 704 | return $exclude ? $array : []; 705 | } 706 | return $exclude ? array_diff_key($array, array_flip($keysArray)) : array_intersect_key($array, array_flip($keysArray)); 707 | } 708 | 709 | /** 710 | * Wrapper around PHP built-in array_filter method.
711 | *
712 | * Iterates over each value in the array passing them to the callback function. If the callback function returns true, the current value from array is returned into the result array. Array keys are preserved. 713 | * 714 | * @param array $array The array to iterate over 715 | * @param callable|null $callback

[optional]

716 | *

The callback function to use

717 | *

If no callback is supplied, all entries of input equal to false (see converting to boolean) will be removed.

718 | * @param int $flag

[optional]

719 | *

Flag determining what arguments are sent to callback:

720 | *