├── .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 | Bayfront Media 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 | } --------------------------------------------------------------------------------