├── .github
├── ISSUE_TEMPLATE
│ ├── 01-bug.yml
│ ├── 02-feature.yml
│ ├── 03-question.yml
│ ├── 04-other.yml
│ └── config.yml
└── SECURITY.md
├── .gitignore
├── CHANGELOG.md
├── LICENSE
├── README.md
├── composer.json
└── src
└── Arr.php
/.github/ISSUE_TEMPLATE/01-bug.yml:
--------------------------------------------------------------------------------
1 | name: ⚠️️ Bug report
2 | description: Report a bug
3 | title: "[BUG]: "
4 | labels: ["Type: Bug"]
5 | body:
6 | - type: markdown
7 | attributes:
8 | value: |
9 | To report a bug, complete the form below.
10 | - type: input
11 | attributes:
12 | label: Project version
13 | description: Version of this project in which the bug exists
14 | placeholder: vX.X.X
15 | validations:
16 | required: true
17 | - type: textarea
18 | attributes:
19 | label: Description
20 | description: Detailed description of the bug
21 | validations:
22 | required: true
23 | - type: textarea
24 | attributes:
25 | label: Expected behavior
26 | description: A summary of what you expected, should this issue not have arisen
27 | - type: textarea
28 | attributes:
29 | label: Possible solution
30 | description: Possible solution/fix to this issue
31 | - type: textarea
32 | attributes:
33 | label: Steps to reproduce
34 | description: Can provide links to a live example, code snippets, screenshots, or simple steps to reproduce this bug
35 | - type: textarea
36 | attributes:
37 | label: Environment
38 | description: Details of the environment which experienced this bug
39 | - type: textarea
40 | attributes:
41 | label: Additional information
42 | description: Additional information/details
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/02-feature.yml:
--------------------------------------------------------------------------------
1 | name: 🛠️ Feature request
2 | description: Request a new feature
3 | title: "[FEATURE]: "
4 | labels: ["Type: Feature"]
5 | body:
6 | - type: markdown
7 | attributes:
8 | value: |
9 | To request a new feature, complete the form below.
10 | - type: input
11 | attributes:
12 | label: Current project version
13 | description: Latest release of this project to-date
14 | placeholder: vX.X.X
15 | validations:
16 | required: true
17 | - type: textarea
18 | attributes:
19 | label: Description
20 | description: Description of the proposed feature
21 | validations:
22 | required: true
23 | - type: textarea
24 | attributes:
25 | label: Scenario/use-case
26 | description: Explain how/when the feature would be helpful
27 | - type: textarea
28 | attributes:
29 | label: Possible solution
30 | description: Possible solution to implement this feature
31 | - type: textarea
32 | attributes:
33 | label: Additional information
34 | description: Additional information/details
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/03-question.yml:
--------------------------------------------------------------------------------
1 | name: ❓ Question
2 | description: Ask a question
3 | title: "[QUESTION]: "
4 | labels: ["Type: Question"]
5 | body:
6 | - type: markdown
7 | attributes:
8 | value: |
9 | To ask a question, complete the form below.
10 | - type: input
11 | attributes:
12 | label: Current project version
13 | description: Latest release of this project to-date
14 | placeholder: vX.X.X
15 | validations:
16 | required: true
17 | - type: textarea
18 | attributes:
19 | label: Description
20 | description: Description of the question
21 | validations:
22 | required: true
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/04-other.yml:
--------------------------------------------------------------------------------
1 | name: 📄 Other
2 | description: All other issues
3 | title: "[OTHER]: "
4 | labels: ["Type: Other"]
5 | body:
6 | - type: markdown
7 | attributes:
8 | value: |
9 | To create a new issue, complete the form below.
10 | - type: input
11 | attributes:
12 | label: Project version
13 | description: Version of this project for which this issue applies (if applicable)
14 | placeholder: vX.X.X
15 | - type: textarea
16 | attributes:
17 | label: Description
18 | description: Issue details
19 | validations:
20 | required: true
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/config.yml:
--------------------------------------------------------------------------------
1 | blank_issues_enabled: false
--------------------------------------------------------------------------------
/.github/SECURITY.md:
--------------------------------------------------------------------------------
1 | # Security Policy
2 |
3 | **PLEASE DO NOT DISCLOSE SECURITY-RELATED ISSUES PUBLICLY**
4 |
5 | If you discover a security vulnerability, please email contact@bayfrontmedia.com.
6 | All security vulnerabilities will be promptly addressed.
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # Project-specific
2 |
3 | *.log
4 |
5 | # Local files
6 |
7 | _local
8 |
9 | # Dotenv
10 |
11 | .env
12 | .env.*
13 | !.env.example
14 |
15 | # Dependencies
16 |
17 | /node_modules
18 | /vendor
19 | composer.lock
20 |
21 | # IDE's
22 |
23 | .idea
24 | .vscode
25 |
26 | # OS
27 |
28 | .DS_Store
29 | .Spotlight-V100
30 | .Trashes
31 | ehthumbs.db
32 | Thumbs.db
--------------------------------------------------------------------------------
/CHANGELOG.md:
--------------------------------------------------------------------------------
1 | # Changelog
2 |
3 | All notable changes to this project will be documented in this file.
4 |
5 | The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
6 | and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7 |
8 | - `Added` for new features.
9 | - `Changed` for changes in existing functionality.
10 | - `Deprecated` for soon-to-be removed features.
11 | - `Removed` for now removed features.
12 | - `Fixed` for any bug fixes.
13 | - `Security` in case of vulnerabilities
14 |
15 | ## [2.0.2] - 2024.12.23
16 |
17 | ### Added
18 |
19 | - Tested up to PHP v8.4.
20 | - Updated GitHub issue templates.
21 |
22 | ## [2.0.1] - 2023.02.03
23 |
24 | ### Fixed
25 |
26 | - Fixed depreciated bug in `query` method
27 |
28 | ## [2.0.0] - 2023.01.26
29 |
30 | ### Added
31 |
32 | - Added support for PHP 8
33 |
34 | ## [1.3.1] - 2021.03.13
35 |
36 | ### Fixed
37 |
38 | - Fixed bug in `multisort` method to preserve array order by adding the `SORT_NUMERIC` flag.
39 |
40 | ## [1.3.0] - 2021.02.17
41 |
42 | ### Added
43 |
44 | - Added the `order` method.
45 |
46 | ## [1.2.0] - 2021.02.05
47 |
48 | ### Added
49 |
50 | - Added the following methods:
51 |
52 | - `getAnyValues`
53 | - `hasAnyValues`
54 | - `hasAllValues`
55 |
56 | ## [1.1.0] - 2020.11.23
57 |
58 | ### Added
59 |
60 | - Added `renameKeys` method.
61 |
62 | ## [1.0.1] - 2020.08.02
63 |
64 | ### Changed
65 |
66 | - Corrected return type for `set()` as `void`
67 |
68 | ## [1.0.0] - 2020.07.27
69 |
70 | ### Added
71 |
72 | - Initial release.
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2020 Bayfront Media
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 | ## PHP array helpers
2 |
3 | PHP helper class to provide useful array functions.
4 |
5 | - [License](#license)
6 | - [Author](#author)
7 | - [Requirements](#requirements)
8 | - [Installation](#installation)
9 | - [Usage](#usage)
10 |
11 | ## License
12 |
13 | This project is open source and available under the [MIT License](LICENSE).
14 |
15 | ## Author
16 |
17 |
18 |
19 | - [Bayfront Media homepage](https://www.bayfrontmedia.com?utm_source=github&utm_medium=direct)
20 | - [Bayfront Media GitHub](https://github.com/bayfrontmedia)
21 |
22 | ## Requirements
23 |
24 | * PHP `^8.0` (Tested up to `8.4`)
25 |
26 | ## Installation
27 |
28 | ```
29 | composer require bayfrontmedia/php-array-helpers
30 | ```
31 |
32 | ## Usage
33 |
34 | - [dot](#dot)
35 | - [undot](#undot)
36 | - [set](#set)
37 | - [has](#has)
38 | - [get](#get)
39 | - [pluck](#pluck)
40 | - [forget](#forget)
41 | - [except](#except)
42 | - [only](#only)
43 | - [missing](#missing)
44 | - [isMissing](#ismissing)
45 | - [multisort](#multisort)
46 | - [renameKeys](#renamekeys)
47 | - [order](#order)
48 | - [query](#query)
49 | - [getAnyValues](#getanyvalues)
50 | - [hasAnyValues](#hasanyvalues)
51 | - [hasAllValues](#hasallvalues)
52 |
53 |
54 |
55 | ### dot
56 |
57 | **Description:**
58 |
59 | Converts a multidimensional array to a single depth "dot" notation array, optionally prepending a string to each array key.
60 |
61 | The key values will never be an array, even if empty. Empty arrays will be dropped.
62 |
63 | **Parameters:**
64 |
65 | - `$array` (array): Original array
66 | - `$prepend = ''` (string): String to prepend
67 |
68 | **Returns:**
69 |
70 | - (array)
71 |
72 | **Example:**
73 |
74 | ```
75 | use Bayfront\ArrayHelpers\Arr;
76 |
77 | $array = [
78 | 'name' => [
79 | 'first_name' => 'John',
80 | 'last_name' => 'Doe'
81 | ],
82 | 'hobbies' => [ // This empty array will be dropped
83 |
84 | ]
85 | ];
86 |
87 | $dot = Arr::dot($array);
88 | ```
89 |
90 |
91 |
92 | ### undot
93 |
94 | **Description:**
95 |
96 | Converts array in "dot" notation to a standard multidimensional array.
97 |
98 | **Parameters:**
99 |
100 | - `$array` (array): Array in "dot" notation
101 |
102 | **Returns:**
103 |
104 | - (array)
105 |
106 | **Example:**
107 |
108 | ```
109 | use Bayfront\ArrayHelpers\Arr;
110 |
111 | $array = [
112 | 'name.first_name' => 'John',
113 | 'name.last_name' => 'Doe'
114 | ];
115 |
116 | $undot = Arr::undot($array);
117 | ```
118 |
119 |
120 |
121 | ### set
122 |
123 | **Description:**
124 |
125 | Set an array item to a given value using "dot" notation.
126 |
127 | **Parameters:**
128 |
129 | - `$array` (array): Original array
130 | - `$key` (string): Key to set in "dot" notation
131 | - `$value` (mixed): Value of key
132 |
133 | **Returns:**
134 |
135 | - (void)
136 |
137 | **Example:**
138 |
139 | ```
140 | use Bayfront\ArrayHelpers\Arr;
141 |
142 | $array = [
143 | 'name' => [
144 | 'first_name' => 'John',
145 | 'last_name' => 'Doe'
146 | ],
147 | ];
148 |
149 | Arr::set($array, 'name.middle_name', 'Middle');
150 | ```
151 |
152 |
153 |
154 | ### has
155 |
156 | **Description:**
157 |
158 | Checks if array key exists and not null using "dot" notation.
159 |
160 | **Parameters:**
161 |
162 | - `$array` (array): Original array
163 | - `$key` (string): Key to check in "dot" notation
164 |
165 | **Returns:**
166 |
167 | - (bool)
168 |
169 | **Example:**
170 |
171 | ```
172 | use Bayfront\ArrayHelpers\Arr;
173 |
174 | $array = [
175 | 'name' => [
176 | 'first_name' => 'John',
177 | 'last_name' => 'Doe'
178 | ],
179 | ];
180 |
181 | if (Arr::has($array, 'name.first_name')) {
182 | // Do something
183 | }
184 | ```
185 |
186 |
187 |
188 | ### get
189 |
190 | **Description:**
191 |
192 | Get an item from an array using "dot" notation, returning an optional default value if not found.
193 |
194 | **Parameters:**
195 |
196 | - `$array` (array): Original array
197 | - `$key` (string): Key to return in "dot" notation
198 | - `$default = NULL` (mixed): Default value to return
199 |
200 | **Returns:**
201 |
202 | - (mixed)
203 |
204 | **Example:**
205 |
206 | ```
207 | use Bayfront\ArrayHelpers\Arr;
208 |
209 | $array = [
210 | 'name' => [
211 | 'first_name' => 'John',
212 | 'last_name' => 'Doe'
213 | ],
214 | ];
215 |
216 | echo Arr::get($array, 'name.first_name');
217 | ```
218 |
219 |
220 |
221 | ### pluck
222 |
223 | **Description:**
224 |
225 | Returns an array of values for a given key from an array using "dot" notation.
226 |
227 | **Parameters:**
228 |
229 | - `$array` (array): Original array
230 | - `$value` (string): Value to return in "dot" notation
231 | - `$key = NULL` (string|null): Optionally how to key the returned array in "dot" notation
232 |
233 | **Returns:**
234 |
235 | - (array)
236 |
237 | **Example:**
238 |
239 | ```
240 | use Bayfront\ArrayHelpers\Arr;
241 |
242 | $array = [
243 | [
244 | 'user_id' => 110,
245 | 'username' => 'John',
246 | 'active' => true
247 | ],
248 | [
249 | 'user_id' => 111,
250 | 'username' => 'Jane',
251 | 'active' => true
252 | ]
253 | ];
254 |
255 | $array = Arr::pluck($array, 'username', 'user_id');
256 | ```
257 |
258 |
259 |
260 | ### forget
261 |
262 | **Description:**
263 |
264 | Remove a single key, or an array of keys from a given array using "dot" notation.
265 |
266 | **Parameters:**
267 |
268 | - `$array` (array): Original array
269 | - `$keys` (string|array): Key(s) to forget in "dot" notation
270 |
271 | **Returns:**
272 |
273 | - (void)
274 |
275 | **Example:**
276 |
277 | ```
278 | use Bayfront\ArrayHelpers\Arr;
279 |
280 | $array = [
281 | 'name' => [
282 | 'first_name' => 'John',
283 | 'last_name' => 'Doe'
284 | ],
285 | ];
286 |
287 | Arr::forget($array, 'name.last_name');
288 | ```
289 |
290 |
291 |
292 | ### except
293 |
294 | **Description:**
295 |
296 | Returns the original array except given key(s).
297 |
298 | **Parameters:**
299 |
300 | - `$array` (array): Original array
301 | - `$keys` (string|array): Key(s) to remove
302 |
303 | **Returns:**
304 |
305 | - (array)
306 |
307 | **Example:**
308 |
309 | ```
310 | use Bayfront\ArrayHelpers\Arr;
311 |
312 | $array = [
313 | 'user_id' => 110,
314 | 'username' => 'John',
315 | 'active' => true
316 | ];
317 |
318 | $array = Arr::except($array, 'active');
319 | ```
320 |
321 |
322 |
323 | ### only
324 |
325 | **Description:**
326 |
327 | Returns only desired key(s) from an array.
328 |
329 | **Parameters:**
330 |
331 | - `$array` (array): Original array
332 | - `$keys` (string|array): Key(s) to return
333 |
334 | **Returns:**
335 |
336 | - (array)
337 |
338 | **Example:**
339 |
340 | ```
341 | use Bayfront\ArrayHelpers\Arr;
342 |
343 | $array = [
344 | 'user_id' => 110,
345 | 'username' => 'John',
346 | 'active' => true
347 | ];
348 |
349 | $array = Arr::only($array, 'username');
350 | ```
351 |
352 |
353 |
354 | ### missing
355 |
356 | **Description:**
357 |
358 | Returns array of missing keys from the original array, or an empty array if none are missing.
359 |
360 | **Parameters:**
361 |
362 | - `$array` (array): Original array
363 | - `$keys` (array): Key(s) to check
364 |
365 | **Returns:**
366 |
367 | - (array)
368 |
369 | **Example:**
370 |
371 | ```
372 | use Bayfront\ArrayHelpers\Arr;
373 |
374 | $array = [
375 | 'user_id' => 110,
376 | 'username' => 'John',
377 | 'active' => true
378 | ];
379 |
380 | $missing = Arr::missing($array, [
381 | 'active',
382 | 'last_login'
383 | ]);
384 | ```
385 |
386 |
387 |
388 | ### isMissing
389 |
390 | **Description:**
391 |
392 | Checks if keys are missing from the original array.
393 |
394 | **Parameters:**
395 |
396 | - `$array` (array): Original array
397 | - `$keys` (array): Key(s) to check
398 |
399 | **Returns:**
400 |
401 | - (bool)
402 |
403 | **Example:**
404 |
405 | ```
406 | use Bayfront\ArrayHelpers\Arr;
407 |
408 | $array = [
409 | 'user_id' => 110,
410 | 'username' => 'John',
411 | 'active' => true
412 | ];
413 |
414 | if (Arr::isMissing($array, [
415 | 'active',
416 | 'last_login'
417 | ])) {
418 | // Do something
419 | }
420 | ```
421 |
422 |
423 |
424 | ### multisort
425 |
426 | **Description:**
427 |
428 | Sort a multidimensional array by a given key in ascending (optionally, descending) order.
429 |
430 | **Parameters:**
431 |
432 | - `$array` (array): Original array
433 | - `$key` (string): Key name to sort by
434 | - `$descending = false` (bool): Sort descending
435 |
436 | **Returns:**
437 |
438 | - (array)
439 |
440 | **Example:**
441 |
442 | ```
443 | use Bayfront\ArrayHelpers\Arr;
444 |
445 | $clients = [
446 | [
447 | 'first_name' => 'John',
448 | 'last_name' => 'Doe'
449 | ],
450 | [
451 | 'first_name' => 'Jane',
452 | 'last_name' => 'Doe'
453 | ]
454 | ];
455 |
456 | $sorted = Arr::multisort($clients, 'first_name');
457 | ```
458 |
459 |
460 |
461 | ### renameKeys
462 |
463 | **Description:**
464 |
465 | Rename array keys while preserving their order.
466 |
467 | **Parameters:**
468 |
469 | - `$array` (array): Original array
470 | - `$keys` (array): Key/value pairs to rename
471 |
472 | **Returns:**
473 |
474 | - (array)
475 |
476 | **Example:**
477 |
478 | ```
479 | use Bayfront\ArrayHelpers\Arr;
480 |
481 | $user = [
482 | 'UserID' => 5,
483 | 'UserEmail' => 'name@example.com',
484 | 'UserGroup' => 'Administrator'
485 | ];
486 |
487 | $renamed = Arr::renameKeys($user, [
488 | 'UserID' => 'id',
489 | 'UserEmail' => 'email',
490 | 'UserGroup' => 'group'
491 | ]);
492 | ```
493 |
494 |
495 |
496 | ### order
497 |
498 | **Description:**
499 |
500 | Order an array based on an array of keys.
501 |
502 | Keys from the `$order` array which do not exist in the original array will be ignored.
503 |
504 | **Parameters:**
505 |
506 | - `$array` (array): Original array
507 | - `$order` (array): Array of keys in the order to be returned
508 |
509 | **Returns:**
510 |
511 | - (array)
512 |
513 | **Example:**
514 |
515 | ```
516 | use Bayfront\ArrayHelpers\Arr;
517 |
518 | $address = [
519 | 'street' => '123 Main St.',
520 | 'state' => 'IL',
521 | 'zip' => '60007',
522 | 'city' => 'Chicago'
523 | ];
524 |
525 | $order = [
526 | 'street',
527 | 'city',
528 | 'state',
529 | 'zip',
530 | 'country'
531 | ];
532 |
533 | $address = Arr::order($address, $order);
534 | ```
535 |
536 | The above example will return the following array:
537 |
538 | ```
539 | Array
540 | (
541 | [street] => 123 Main St.
542 | [city] => Chicago
543 | [state] => IL
544 | [zip] => 60007
545 | )
546 | ```
547 |
548 |
549 |
550 | ### query
551 |
552 | **Description:**
553 |
554 | Convert array into a query string.
555 |
556 | **Parameters:**
557 |
558 | - `$array` (array): Original array
559 |
560 | **Returns:**
561 |
562 | - (string)
563 |
564 | **Example:**
565 |
566 | ```
567 | use Bayfront\ArrayHelpers\Arr;
568 |
569 | $array = [
570 | 'first_name' => 'Jane',
571 | 'last_name' => 'Doe'
572 | ];
573 |
574 | echo Arr::query($array);
575 | ```
576 |
577 |
578 |
579 | ### getAnyValues
580 |
581 | **Description:**
582 |
583 | Return an array of values which exist in a given array.
584 |
585 | **Parameters:**
586 |
587 | - `$array` (array)
588 | - `$values` (array)
589 |
590 | **Returns:**
591 |
592 | - (array)
593 |
594 | **Example:**
595 |
596 | ```
597 | $array = [
598 | 'name' => [
599 | 'John',
600 | 'Dave'
601 | ],
602 | ];
603 |
604 | $existing_values = Arr::getAnyValues($array['name'], [
605 | 'John',
606 | 'Jane'
607 | ]);
608 | ```
609 |
610 |
611 |
612 | ### hasAnyValues
613 |
614 | **Description:**
615 |
616 | Do any values exist in a given array.
617 |
618 | **Parameters:**
619 |
620 | - `$array` (array)
621 | - `$values` (array)
622 |
623 | **Returns:**
624 |
625 | - (bool)
626 |
627 | **Example:**
628 |
629 | ```
630 | $array = [
631 | 'name' => [
632 | 'John',
633 | 'Dave'
634 | ],
635 | ];
636 |
637 | if (Arr::hasAnyValues($array['name'], [
638 | 'John',
639 | 'Jane'
640 | ])) {
641 | // Do something
642 | }
643 | ```
644 |
645 |
646 |
647 | ### hasAllValues
648 |
649 | **Description:**
650 |
651 | Do all values exist in a given array.
652 |
653 | **Parameters:**
654 |
655 | - `$array` (array)
656 | - `$values` (array)
657 |
658 | **Returns:**
659 |
660 | - (bool)
661 |
662 | **Example:**
663 |
664 | ```
665 | $array = [
666 | 'name' => [
667 | 'John',
668 | 'Dave'
669 | ],
670 | ];
671 |
672 | if (Arr::hasAllValues($array['name'], [
673 | 'John',
674 | 'Jane'
675 | ])) {
676 | // Do something
677 | }
678 | ```
--------------------------------------------------------------------------------
/composer.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "bayfrontmedia/php-array-helpers",
3 | "description": "Helper class to provide useful array functions.",
4 | "homepage": "https://github.com/bayfrontmedia/php-array-helpers",
5 | "license" : "MIT",
6 | "type": "library",
7 | "keywords": [
8 | "php",
9 | "array",
10 | "helper",
11 | "helpers",
12 | "function"
13 | ],
14 | "authors": [
15 | {
16 | "name": "John Robinson",
17 | "email": "john@bayfrontmedia.com",
18 | "homepage": "https://www.bayfrontmedia.com"
19 | }
20 | ],
21 | "support": {
22 | "issues": "https://github.com/bayfrontmedia/php-array-helpers/issues"
23 | },
24 | "config": {
25 | "optimize-autoloader": true,
26 | "preferred-install": "dist"
27 | },
28 | "require": {
29 | "php": "^8.0"
30 | },
31 | "autoload": {
32 | "psr-4": {
33 | "Bayfront\\ArrayHelpers\\": "src/"
34 | }
35 | }
36 | }
--------------------------------------------------------------------------------
/src/Arr.php:
--------------------------------------------------------------------------------
1 | $value) {
28 |
29 | if (is_array($value)) {
30 |
31 | $results = array_merge($results, self::dot($value, $prepend . $key . '.'));
32 |
33 | } else {
34 |
35 | $results[$prepend . $key] = $value;
36 |
37 | }
38 |
39 | // Empty arrays are not returned
40 |
41 | }
42 |
43 | return $results;
44 |
45 | }
46 |
47 | /**
48 | * Converts array in "dot" notation to a standard multidimensional array.
49 | *
50 | * @param array $array (Array in "dot" notation)
51 | *
52 | * @return array
53 | */
54 |
55 | public static function undot(array $array): array
56 | {
57 |
58 | $return = [];
59 |
60 | foreach ($array as $key => $value) {
61 |
62 | self::set($return, $key, $value);
63 |
64 | }
65 |
66 | return $return;
67 |
68 | }
69 |
70 | /**
71 | * Set an array item to a given value using "dot" notation.
72 | *
73 | * @param array $array (Original array)
74 | * @param string $key (Key to set in "dot" notation)
75 | * @param mixed $value (Value of key)
76 | *
77 | * @return void
78 | */
79 |
80 | public static function set(array &$array, string $key, mixed $value): void
81 | {
82 |
83 | $keys = explode('.', $key);
84 |
85 | while (count($keys) > 1) {
86 |
87 | $key = array_shift($keys);
88 |
89 | /*
90 | * If the key doesn't exist at this depth, an empty array is created
91 | * to hold the next value, allowing to create the arrays to hold final
92 | * values at the correct depth. Then, keep digging into the array.
93 | */
94 |
95 | if (!isset($array[$key]) || !is_array($array[$key])) {
96 |
97 | $array[$key] = [];
98 |
99 | }
100 |
101 | $array = &$array[$key];
102 |
103 | }
104 |
105 | $array[array_shift($keys)] = $value;
106 |
107 | }
108 |
109 | /**
110 | * Checks if array key exists and not null using "dot" notation.
111 | *
112 | * @param array $array (Original array)
113 | * @param string $key (Key to check in "dot" notation)
114 | *
115 | * @return bool
116 | */
117 |
118 | public static function has(array $array, string $key): bool
119 | {
120 | return NULL !== self::get($array, $key);
121 | }
122 |
123 | /**
124 | * Get an item from an array using "dot" notation, returning an optional default value if not found.
125 | *
126 | * @param array $array (Original array)
127 | * @param string $key (Key to return in "dot" notation)
128 | * @param mixed|null $default (Default value to return)
129 | *
130 | * @return mixed
131 | */
132 |
133 | public static function get(array $array, string $key, mixed $default = NULL): mixed
134 | {
135 |
136 | if (isset($array[$key])) {
137 |
138 | return $array[$key];
139 |
140 | }
141 |
142 | foreach (explode('.', $key) as $segment) {
143 |
144 | if (!is_array($array) || !array_key_exists($segment, $array)) {
145 |
146 | return $default;
147 |
148 | }
149 |
150 | $array = $array[$segment];
151 |
152 | }
153 |
154 | return $array;
155 |
156 | }
157 |
158 | /**
159 | * Returns an array of values for a given key from an array using "dot" notation.
160 | *
161 | * @param array $array (Original array)
162 | * @param string $value (Value to return in "dot" notation)
163 | * @param string|null $key (Optionally how to key the returned array in "dot" notation)
164 | *
165 | * @return array
166 | */
167 |
168 | public static function pluck(array $array, string $value, ?string $key = NULL): array
169 | {
170 | $results = [];
171 |
172 | foreach ($array as $item) {
173 |
174 | $itemValue = self::get($item, $value);
175 |
176 | if (is_null($key)) {
177 |
178 | $results[] = $itemValue;
179 |
180 | } else {
181 |
182 | $itemKey = self::get($item, $key);
183 |
184 | $results[$itemKey] = $itemValue;
185 |
186 | }
187 |
188 | }
189 |
190 | return $results;
191 | }
192 |
193 | /**
194 | * Remove a single key, or an array of keys from a given array using "dot" notation.
195 | *
196 | * @param array $array (Original array)
197 | * @param array|string $keys (Key(s) to forget in "dot" notation)
198 | *
199 | * @return void
200 | */
201 |
202 | public static function forget(array &$array, array|string $keys): void
203 | {
204 |
205 | $original =& $array;
206 |
207 | foreach ((array)$keys as $key) {
208 |
209 | $parts = explode('.', $key);
210 |
211 | while (count($parts) > 1) {
212 |
213 | $part = array_shift($parts);
214 |
215 | if (isset($array[$part]) && is_array($array[$part])) {
216 |
217 | $array =& $array[$part];
218 |
219 | }
220 |
221 | }
222 |
223 | unset($array[array_shift($parts)]);
224 |
225 | // Clean up after each iteration
226 |
227 | $array =& $original;
228 |
229 | }
230 | }
231 |
232 | /**
233 | * Returns the original array except given key(s).
234 | *
235 | * @param array $array (Original array)
236 | * @param array|string $keys (Keys to remove)
237 | *
238 | * @return array
239 | */
240 |
241 | public static function except(array $array, array|string $keys): array
242 | {
243 | return array_diff_key($array, array_flip((array)$keys));
244 | }
245 |
246 | /**
247 | * Returns only desired key(s) from an array.
248 | *
249 | * @param array $array (Original array)
250 | * @param array|string $keys (Keys to return)
251 | *
252 | * @return array
253 | */
254 |
255 | public static function only(array $array, array|string $keys): array
256 | {
257 | return array_intersect_key($array, array_flip((array)$keys));
258 | }
259 |
260 | /**
261 | * Returns array of missing keys from the original array, or an empty array if none are missing.
262 | *
263 | * @param array $array (Original array)
264 | * @param array|string $keys (Keys to check)
265 | *
266 | * @return array
267 | */
268 |
269 | public static function missing(array $array, array|string $keys): array
270 | {
271 | return array_values(array_flip(array_diff_key(array_flip((array)$keys), $array)));
272 | }
273 |
274 | /**
275 | * Checks if keys are missing from the original array
276 | *
277 | * @param array $array (Original array)
278 | * @param array|string $keys (Keys to check)
279 | *
280 | * @return bool
281 | */
282 |
283 | public static function isMissing(array $array, array|string $keys): bool
284 | {
285 | return (bool)self::missing($array, $keys);
286 | }
287 |
288 | /**
289 | * Sort a multidimensional array by a given key in ascending (optionally, descending) order.
290 | *
291 | * @param array $array (Original array)
292 | * @param string $key (Key name to sort by)
293 | * @param bool $descending (Sort descending)
294 | *
295 | * @return array
296 | */
297 |
298 | public static function multisort(array $array, string $key, bool $descending = false): array
299 | {
300 |
301 | $columns = array_column($array, $key);
302 |
303 | if (false === $descending) {
304 |
305 | array_multisort($columns, SORT_ASC, $array, SORT_NUMERIC);
306 |
307 | } else {
308 |
309 | array_multisort($columns, SORT_DESC, $array, SORT_NUMERIC);
310 |
311 | }
312 |
313 | return $array;
314 |
315 | }
316 |
317 | /**
318 | * Rename array keys while preserving their order.
319 | *
320 | * @param array $array (Original array)
321 | * @param array $keys (Key/value pairs to rename)
322 | *
323 | * @return array
324 | */
325 |
326 | public static function renameKeys(array $array, array $keys): array
327 | {
328 |
329 | $new_array = [];
330 |
331 | foreach ($array as $k => $v) {
332 |
333 | if (array_key_exists($k, $keys)) {
334 |
335 | $new_array[$keys[$k]] = $v;
336 |
337 | } else {
338 |
339 | $new_array[$k] = $v;
340 |
341 | }
342 |
343 | }
344 |
345 | return $new_array;
346 |
347 | }
348 |
349 | /**
350 | * Order an array based on an array of keys.
351 | *
352 | * Keys from the $order array which do not exist in the original array will be ignored.
353 | *
354 | * @param array $array (Original array)
355 | * @param array $order (Array of keys in the order to be returned)
356 | *
357 | * @return array
358 | */
359 |
360 | public static function order(array $array, array $order): array
361 | {
362 | return self::only(array_replace(array_flip($order), $array), array_keys($array));
363 | }
364 |
365 | /**
366 | * Convert array into a query string.
367 | *
368 | * @param array $array (Original array)
369 | *
370 | * @return string
371 | */
372 |
373 | public static function query(array $array): string
374 | {
375 | return http_build_query($array, '', '&', PHP_QUERY_RFC3986);
376 | }
377 |
378 | /**
379 | * Return an array of values which exist in a given array.
380 | *
381 | * @param array $array
382 | * @param array $values
383 | *
384 | * @return array
385 | */
386 |
387 | public static function getAnyValues(array $array, array $values): array
388 | {
389 | return array_intersect($values, Arr::dot($array));
390 | }
391 |
392 | /**
393 | * Do any values exist in a given array.
394 | *
395 | * @param array $array
396 | * @param array $values
397 | *
398 | * @return bool
399 | */
400 |
401 | public static function hasAnyValues(array $array, array $values): bool
402 | {
403 | return !empty(self::getAnyValues($array, $values));
404 | }
405 |
406 | /**
407 | * Do all values exist in a given array.
408 | *
409 | * @param array $array
410 | * @param array $values
411 | *
412 | * @return bool
413 | */
414 |
415 | public static function hasAllValues(array $array, array $values): bool
416 | {
417 | return count(array_intersect($values, Arr::dot($array))) == count($values);
418 | }
419 |
420 | }
--------------------------------------------------------------------------------