├── LICENSE ├── README.md ├── _config.yml └── translations ├── bn.md ├── es-AR.md └── pt-BR.md /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2021 BECHER Arnaud 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 | # Modern PHP Cheatsheet 2 | 3 | ![Modern PHP Cheatsheet](https://i.imgur.com/2STEtgG.png) 4 | 5 | 6 | > If you like this content, you can ping me or follow me on Twitter :+1: 7 | 8 | [![Tweet for help](https://img.shields.io/twitter/follow/smknstd?label=Tweet%20%40smknstd&style=social)](https://twitter.com/smknstd/) 9 | 10 | ## Introduction 11 | 12 | ### Motivation 13 | 14 | This document is a cheatsheet for PHP you will frequently encounter in modern projects and most contemporary sample code. 15 | 16 | This guide is not intended to teach you PHP from the ground up, but to help developers with basic knowledge who may struggle to get familiar with modern codebases (or let's say to learn Laravel or Symfony for instance) because of the new PHP concepts and features introduced over the years. 17 | 18 | > **Note:** Concepts introduced here are based on the most recent version of PHP available ([PHP 8.3](https://www.php.net/releases/8.3/en.php) at the time of the last update) 19 | 20 | ### Complementary Resources 21 | 22 | When you struggle to understand a notion, I suggest you look for answers on the following resources: 23 | - [Stitcher's blog](https://stitcher.io/blog) 24 | - [PHP.Watch](https://php.watch/versions) 25 | - [Exploring PHP 8.0](https://leanpub.com/exploringphp80) 26 | - [PHP 8 in a nutshell](https://amitmerchant.gumroad.com/l/php8-in-a-nutshell) 27 | - [PHP The Right Way](https://phptherightway.com/) 28 | - [StackOverflow](https://stackoverflow.com/questions/tagged/php) 29 | 30 | ### Recent PHP releases 31 | 32 | | Version | Release date | 33 | |----------------------------------------------------|---------------| 34 | | [PHP 8.4](https://www.php.net/releases/8.4/en.php) | November 2024 | 35 | | [PHP 8.3](https://www.php.net/releases/8.3/en.php) | December 2023 | 36 | | [PHP 8.2](https://www.php.net/releases/8.2/en.php) | December 2022 | 37 | | [PHP 8.1](https://www.php.net/releases/8.1/en.php) | November 2021 | 38 | | [PHP 8.0](https://www.php.net/releases/8.0/en.php) | November 2020 | 39 | | PHP 7.4 | November 2019 | 40 | | PHP 7.3 | December 2018 | 41 | | PHP 7.2 | November 2017 | 42 | | PHP 7.1 | December 2016 | 43 | | PHP 7.0 | December 2015 | 44 | 45 | More infos on [php.net](https://www.php.net/supported-versions.php). 46 | 47 | ## Table of Contents 48 | 49 | - [Modern PHP cheatsheet](#modern-php-cheatsheet) 50 | * [Introduction](#introduction) 51 | + [Motivation](#motivation) 52 | + [Complementary resources](#complementary-resources) 53 | + [Recent PHP releases](#recent-php-releases) 54 | * [Table of contents](#table-of-contents) 55 | * [Notions](#notions) 56 | + [Function default parameter value](#function-default-parameter-value) 57 | + [Trailing comma](#trailing-comma) 58 | + [Type declaration](#type-declaration) 59 | + [Destructuring arrays](#destructuring-arrays) 60 | + [Null Coalescing](#null-coalescing) 61 | + [Nullsafe operator](#nullsafe-operator) 62 | + [Spread operator](#spread-operator) 63 | + [Named arguments](#named-arguments) 64 | + [Short closures](#short-closures) 65 | + [Match expression](#match-expression) 66 | + [Stringable interface](#stringable-interface) 67 | + [Enums](#enums) 68 | + [Multiple lines string syntax](#multiple-lines-string-syntax) 69 | 70 | ## Notions 71 | 72 | ### Function default parameter value 73 | 74 | You can set default value to your function parameters: 75 | 76 | ```php 77 | function myFunction($param = 'foo') 78 | { 79 | return $param; 80 | } 81 | $a = myFunction(); 82 | // $a = 'foo' 83 | 84 | $b = myFunction('bar'); 85 | // $b = 'bar' 86 | ``` 87 | 88 | But if you send null or an undefined property, default value won't be used: 89 | 90 | ```php 91 | function myFunction($param = 'foo') 92 | { 93 | return $param; 94 | } 95 | $a = myFunction(null); 96 | // $a = null 97 | 98 | $b = myFunction($undefined); // PHP Warning: Undefined variable $undefined 99 | // $b = null 100 | ``` 101 | 102 | ### Trailing comma 103 | 104 | A trailing comma, also known as a dangling comma, is a comma symbol that is typed after the last item of a list of elements. One of the major benefits when used with multilines, is that [diff outputs are cleaner](https://medium.com/@nikgraf/why-you-should-enforce-dangling-commas-for-multiline-statements-d034c98e36f8). 105 | 106 | #### Array 107 | 108 | You can use trailing comma in arrays : 109 | 110 | ```php 111 | $array = [ 112 | 'foo', 113 | 'bar', 114 | ]; 115 | ``` 116 | 117 | #### Grouped use statement 118 | 119 | ![php-version-72](https://shields.io/badge/php->=7.2-blue) 120 | 121 | Since PHP 7.2, you can use trailing comma in grouped use statement: 122 | 123 | ```php 124 | use Symfony\Component\HttpKernel\{ 125 | Controller\ControllerResolverInterface, 126 | Exception\NotFoundHttpException, 127 | Event\PostResponseEvent, 128 | }; 129 | ``` 130 | 131 | #### Function and method call 132 | 133 | ![php-version-73](https://shields.io/badge/php->=7.3-blue) 134 | 135 | Since PHP 7.3, you can use trailing comma when calling a function: 136 | 137 | ```php 138 | function myFunction($foo, $bar) 139 | { 140 | return true; 141 | } 142 | $a = myFunction( 143 | 'baz', 144 | 'qux', 145 | ); 146 | ``` 147 | 148 | and when calling a method: 149 | 150 | ```php 151 | $f = new Foo(); 152 | $f->myMethod( 153 | 'baz', 154 | 'qux', 155 | ); 156 | ``` 157 | 158 | #### Function parameters 159 | 160 | ![php-version-80](https://shields.io/badge/php->=8.0-blue) 161 | 162 | Since PHP 8.0, you can use trailing comma when declaring function parameters: 163 | 164 | ```php 165 | function myFunction( 166 | $foo, 167 | $bar, 168 | ) 169 | { 170 | return true; 171 | } 172 | ``` 173 | 174 | #### Closure's use statement 175 | 176 | ![php-version-80](https://shields.io/badge/php->=8.0-blue) 177 | 178 | Since PHP 8.0, you can use trailing comma with closure's use statement: 179 | 180 | ```php 181 | function() use ( 182 | $foo, 183 | $bar, 184 | ) 185 | { 186 | return true; 187 | } 188 | ``` 189 | 190 | ### Type declaration 191 | 192 | ![php-version-70](https://shields.io/badge/php->=7.0-blue) 193 | 194 | With Type declaration you can specify the expected data type for a property that will be enforce at runtime. It supports many types like scalar types (int, string, bool, and float) but also array, iterable, object, stdClass, etc. 195 | 196 | You can set a type to a function's parameter: 197 | 198 | ```php 199 | function myFunction(int $param) 200 | { 201 | return $param; 202 | } 203 | $a = myFunction(10); 204 | // $a = 10 205 | $b = myFunction('foo'); // TypeError: myFunction(): Argument #1 ($param) must be of type int, string given 206 | ``` 207 | 208 | You can set a return type to a function: 209 | 210 | ```php 211 | function myFunction(): int 212 | { 213 | return 'foo'; 214 | } 215 | $a = myFunction(); // TypeError: myFunction(): Return value must be of type int, string returned 216 | ``` 217 | 218 | When a function should not return something, you can use the type "void": 219 | 220 | ```php 221 | function myFunction(): void 222 | { 223 | return 'foo'; 224 | } 225 | // PHP Fatal error: A void function must not return a value 226 | ``` 227 | 228 | You cannot return null either: 229 | 230 | ```php 231 | function myFunction(): void 232 | { 233 | return null; 234 | } 235 | // PHP Fatal error: A void function must not return a value 236 | ``` 237 | 238 | However, using return to exit the function is valid: 239 | 240 | ```php 241 | function myFunction(): void 242 | { 243 | return; 244 | } 245 | $a = myFunction(); 246 | // $a = null 247 | ``` 248 | 249 | #### Class property 250 | 251 | ![php-version-74](https://shields.io/badge/php->=7.4-blue) 252 | 253 | You can set a type to a class property: 254 | 255 | ```php 256 | Class Foo 257 | { 258 | public int $bar; 259 | } 260 | $f = new Foo(); 261 | $f->bar = 'baz'; // TypeError: Cannot assign string to property Foo::$bar of type int 262 | ``` 263 | 264 | #### Union type 265 | 266 | ![php-version-80](https://shields.io/badge/php->=8.0-blue) 267 | 268 | Since PHP 8.0, you can use a “union type” that accepts values of multiple different types, rather than a single one: 269 | 270 | ```php 271 | function myFunction(string|int|array $param): string|int|array 272 | { 273 | return $param; 274 | } 275 | ``` 276 | 277 | It also works with class property: 278 | 279 | ```php 280 | Class Foo 281 | { 282 | public string|int|array $bar; 283 | } 284 | ``` 285 | 286 | #### Intersection type 287 | 288 | ![php-version-81](https://shields.io/badge/php->=8.1-blue) 289 | 290 | Since PHP 8.1, you can use an "intersection type" (also known as "pure") that enforce that a given value belong to every types. For example this param needs to implement both *Stringable* and *Countable* interfaces: 291 | 292 | ```php 293 | function myFunction(Stringable&Countable $param): Stringable&Countable 294 | { 295 | return $param; 296 | } 297 | Class Foo 298 | { 299 | public function __toString() { 300 | return "something"; 301 | } 302 | } 303 | myFunction(new Foo()); 304 | // TypeError: myFunction(): Argument #1 ($param) must be of type Stringable&Countable, Foo given 305 | ``` 306 | 307 | It also works with class property: 308 | 309 | ```php 310 | Class Foo 311 | { 312 | public Stringable&Countable $bar; 313 | } 314 | ``` 315 | 316 | Intersection type only supports class and interfaces. Scalar types (string, int, array, null, mixed, etc) are not allowed: 317 | 318 | ```php 319 | function myFunction(string&Countable $param) 320 | { 321 | return $param; 322 | } 323 | // PHP Fatal error: Type string cannot be part of an intersection type 324 | ``` 325 | 326 | ##### External resource 327 | 328 | - [Intersection types on PHP.Watch](https://php.watch/versions/8.1/intersection-types) 329 | 330 | #### Nullable type 331 | 332 | ![php-version-71](https://shields.io/badge/php->=7.1-blue) 333 | 334 | When a parameter has no type, it can accept null value: 335 | 336 | ```php 337 | function myFunction($param) 338 | { 339 | return $param; 340 | } 341 | $a = myFunction(null); 342 | // $a = null 343 | ``` 344 | 345 | But as soon as a parameter has a type, it won't accept null value anymore and you'll get an error: 346 | 347 | ```php 348 | function myFunction(string $param) 349 | { 350 | return $param; 351 | } 352 | $a = myFunction(null); // TypeError: myFunction(): Argument #1 ($param) must be of type string, null given 353 | ``` 354 | 355 | If a function has a return type, it won't accept null value either: 356 | 357 | ```php 358 | function myFunction(): string 359 | { 360 | return null; 361 | } 362 | $a = myFunction(); // TypeError: myFunction(): Return value must be of type string, null returned 363 | ``` 364 | 365 | You can make a type declaration explicitly nullable: 366 | 367 | ```php 368 | function myFunction(?string $param) 369 | { 370 | return $param; 371 | } 372 | $a = myFunction(null); 373 | // $a = null 374 | ``` 375 | 376 | or with a union type: 377 | 378 | ```php 379 | function myFunction(string|null $param) 380 | { 381 | return $param; 382 | } 383 | $a = myFunction(null); 384 | // $a = null 385 | ``` 386 | 387 | It also works with return type: 388 | 389 | ```php 390 | function myFunction(?string $param): ?string 391 | { 392 | return $param; 393 | } 394 | // or 395 | function myFunction(string|null $param): string|null 396 | { 397 | return $param; 398 | } 399 | ``` 400 | 401 | But void cannot be nullable: 402 | 403 | ```php 404 | function myFunction(): ?void 405 | { 406 | // some code 407 | } 408 | // PHP Fatal error: Void type cannot be nullable 409 | ``` 410 | 411 | or 412 | 413 | ```php 414 | function myFunction(): void|null 415 | { 416 | // some code 417 | } 418 | // PHP Fatal error: Void type cannot be nullable 419 | ``` 420 | 421 | You can set a nullable type to a class property: 422 | 423 | ```php 424 | Class Foo 425 | { 426 | public int|null $bar; 427 | } 428 | $f = new Foo(); 429 | $f->bar = null; 430 | $a = $f->bar; 431 | // $a = null 432 | ``` 433 | 434 | ### Destructuring arrays 435 | 436 | You can destructure arrays to pull out several elements into separate variables. 437 | 438 | #### Indexed array 439 | 440 | ![php-version-40](https://shields.io/badge/php->=4.0-blue) 441 | 442 | Considering an indexed array like : 443 | 444 | ```php 445 | $array = ['foo', 'bar', 'baz']; 446 | ``` 447 | 448 | You can destruct it using the list syntax: 449 | 450 | ```php 451 | list($a, $b, $c) = $array; 452 | 453 | // $a = 'foo' 454 | // $b = 'bar' 455 | // $c = 'baz' 456 | ``` 457 | 458 | Or since PHP 7.1, the shorthand syntax: 459 | 460 | ```php 461 | [$a, $b, $c] = $array; 462 | 463 | // $a = 'foo' 464 | // $b = 'bar' 465 | // $c = 'baz' 466 | ``` 467 | 468 | You can skip elements: 469 | 470 | ```php 471 | list(, , $c) = $array; 472 | 473 | // $c = 'baz' 474 | ``` 475 | 476 | Or since PHP 7.1, the shorthand syntax: 477 | 478 | ```php 479 | [, , $c] = $array; 480 | 481 | // $c = 'baz' 482 | ``` 483 | 484 | When you try to destruct an index that doesn't exist in the given array, you'll get a warning: 485 | 486 | ```php 487 | list($a, $b, $c, $d) = $array; // PHP Warning: Undefined array key 3 488 | 489 | // $a = 'foo' 490 | // $b = 'bar' 491 | // $c = 'baz' 492 | // $d = null; 493 | ``` 494 | 495 | You can also swap variables with destructuring assignments, considering you have variable like: 496 | ```php 497 | $a = 'foo'; 498 | $b = 'bar'; 499 | ``` 500 | 501 | So if you want to swap `$a` and `$b` instead of using a temporary variable like this: 502 | 503 | ```php 504 | $temp = $a; 505 | $a = $b; 506 | $b = $temp; 507 | 508 | // $a = 'bar' 509 | // $b = 'foo' 510 | ``` 511 | 512 | You can swap it using the list syntax: 513 | 514 | ```php 515 | list($a, $b) = [$b, $a]; 516 | 517 | // $a = 'bar' 518 | // $b = 'foo' 519 | ``` 520 | 521 | Or since PHP 7.1, the shorthand syntax: 522 | 523 | ```php 524 | [$a, $b] = [$b, $a]; 525 | 526 | // $a = 'bar' 527 | // $b = 'foo' 528 | ``` 529 | 530 | #### Associative array 531 | 532 | ![php-version-71](https://shields.io/badge/php->=7.1-blue) 533 | 534 | Considering an associative array (string-keyed) like : 535 | 536 | ```php 537 | $array = [ 538 | 'foo' => 'value1', 539 | 'bar' => 'value2', 540 | 'baz' => 'value3', 541 | ]; 542 | ``` 543 | 544 | Previous list syntax won't work with an associative array, and you'll get a warning: 545 | 546 | ```php 547 | list($a, $b, $c) = $array; // PHP Warning: Undefined array key 0 ... 548 | 549 | // $a = null 550 | // $b = null 551 | // $c = null 552 | ``` 553 | 554 | But since PHP 7.1, you can destruct it with another syntax based on keys: 555 | 556 | ```php 557 | list('foo' => $a, 'bar' => $b, 'baz' => $c) = $array; 558 | 559 | // $a = 'value1' 560 | // $b = 'value2' 561 | // $c = 'value3' 562 | ``` 563 | 564 | Or the shorthand syntax: 565 | 566 | ```php 567 | ['foo' => $a, 'bar' => $b, 'baz' => $c] = $array; 568 | 569 | // $a = 'value1' 570 | // $b = 'value2' 571 | // $c = 'value3' 572 | ``` 573 | 574 | You can also destruct only a portion of the array (The order doesn't matter): 575 | 576 | ```php 577 | ['baz' => $c, 'foo' => $a] = $array; 578 | 579 | // $a = 'value1' 580 | // $c = 'value3' 581 | ``` 582 | 583 | When you try to destruct a key that doesn't exist in the given array, you'll get a warning: 584 | 585 | ```php 586 | list('moe' => $d) = $array; // PHP Warning: Undefined array key "moe" 587 | 588 | // $d = null 589 | ``` 590 | 591 | ### Null Coalescing 592 | 593 | ![php-version-70](https://shields.io/badge/php->=7.0-blue) 594 | 595 | Since PHP 7.0, you can use the null coalescing operator to provide a fallback when a property is null with no error nor warning: 596 | 597 | ```php 598 | $a = null; 599 | $b = $a ?? 'fallback'; 600 | 601 | // $b = 'fallback' 602 | ``` 603 | 604 | It is equivalent to: 605 | 606 | ```php 607 | $a = null; 608 | $b = isset($a) ? $a : 'fallback'; 609 | // $b = 'fallback' 610 | ``` 611 | 612 | It also works when property is undefined: 613 | 614 | ```php 615 | $a = $undefined ?? 'fallback'; 616 | 617 | // $a = 'fallback' 618 | ``` 619 | 620 | Every other value of the property won't trigger the fallback: 621 | 622 | ```php 623 | '' ?? 'fallback'; // '' 624 | 0 ?? 'fallback'; // 0 625 | false ?? 'fallback'; // false 626 | ``` 627 | 628 | You can chain null coalescing multiple times: 629 | 630 | ```php 631 | $a = null; 632 | $b = null; 633 | $c = $a ?? $b ?? 'fallback'; 634 | // $c = 'fallback' 635 | ``` 636 | 637 | #### Elvis operator 638 | 639 | ![php-version-53](https://shields.io/badge/php->=5.3-blue) 640 | 641 | It should not be confused with the shorthand ternary operator (aka the elvis operator), which was introduced in PHP 5.3: 642 | 643 | ```php 644 | $a = null; 645 | $b = $a ?: 'fallback'; 646 | 647 | // $b = 'fallback' 648 | ``` 649 | 650 | The shorthand ternary operator is equivalent to: 651 | 652 | ```php 653 | $a = null; 654 | $b = $a ? $a : 'fallback'; 655 | // $b = 'fallback' 656 | ``` 657 | 658 | Result between null coalescing and elvis operator can be similar, but also different for some specific values: 659 | 660 | ```php 661 | '' ?: 'fallback'; // 'fallback' 662 | 0 ?: 'fallback'; // 'fallback' 663 | false ?: 'fallback'; // 'fallback' 664 | ``` 665 | 666 | #### Null coalescing on array 667 | 668 | If array key exists, then fallback isn't triggered: 669 | 670 | ```php 671 | $a = ['foo' => 'bar']; 672 | $b = $a['foo'] ?? 'fallback'; 673 | 674 | // $b = 'bar' 675 | ``` 676 | 677 | But when array doesn't exist, fallback is triggered with no error nor warning: 678 | 679 | ```php 680 | $a = null; 681 | $b = $a['foo'] ?? 'fallback'; 682 | 683 | // $b = 'fallback' 684 | ``` 685 | 686 | Or array property is undefined, fallback is triggered with no error nor warning: 687 | 688 | ```php 689 | $b = $undefined['foo'] ?? 'fallback'; 690 | 691 | // $b = 'fallback' 692 | ``` 693 | 694 | When array exist but key can't be found in the given array, fallback is triggered with no error nor warning: 695 | 696 | ```php 697 | $a = []; 698 | $b = $a['foo'] ?? 'fallback'; 699 | 700 | // $b = 'fallback' 701 | ``` 702 | 703 | It also works with indexed arrays: 704 | 705 | ```php 706 | $a = ['foo']; 707 | 708 | // reminder: $a[0] = 'foo' 709 | 710 | $b = $a[1] ?? 'fallback'; 711 | 712 | // $b = 'fallback' 713 | ``` 714 | 715 | It also works with nested arrays. If nested array key exists, then fallback isn't triggered: 716 | 717 | ```php 718 | $a = [ 719 | 'foo' => [ 720 | 'bar' => 'baz' 721 | ] 722 | ]; 723 | $b = $a['foo']['bar'] ?? 'fallback'; 724 | 725 | // $b = 'baz' 726 | ``` 727 | 728 | But when nested key can't be found in the given array, fallback is triggered with no error nor warning: 729 | 730 | ```php 731 | $a = [ 732 | 'foo' => [ 733 | 'bar' => 'baz' 734 | ] 735 | ]; 736 | $b = $a['foo']['qux'] ?? 'fallback'; 737 | 738 | // $b = 'fallback' 739 | ``` 740 | 741 | #### Null coalescing on object 742 | 743 | You can also use null coalescing operator with object. 744 | 745 | ##### Object's attribute 746 | 747 | If object's attribute exists, then fallback isn't triggered: 748 | 749 | ```php 750 | $a = (object)[ 751 | 'foo' => 'bar' 752 | ]; 753 | $b = $a->foo ?? 'fallback'; 754 | 755 | // $b = 'bar' 756 | ``` 757 | 758 | But when object's attribute can't be found, fallback is triggered with no error nor warning: 759 | 760 | ```php 761 | $a = (object)[ 762 | 'foo' => 'bar' 763 | ]; 764 | $b = $a->baz ?? 'fallback'; 765 | 766 | // $b = 'fallback' 767 | ``` 768 | 769 | ##### Object's method 770 | 771 | You can also use the null coalescing operator on call to an object's method. If the given method exists, then fallback isn't triggered: 772 | 773 | ```php 774 | class Foo 775 | { 776 | public function bar() 777 | { 778 | return 'baz'; 779 | } 780 | } 781 | 782 | $a = new Foo(); 783 | $b = $a->bar() ?? 'fallback'; 784 | 785 | // $b = 'baz' 786 | ``` 787 | 788 | But when object's method returns null, fallback is triggered with no error nor warning: 789 | 790 | ```php 791 | class Foo 792 | { 793 | public function bar() 794 | { 795 | return null; 796 | } 797 | } 798 | 799 | $a = new Foo(); 800 | $b = $a->bar() ?? 'fallback'; 801 | 802 | // $b = 'fallback' 803 | ``` 804 | 805 | If object's method can't be found, null coalescing won't work and you'll get an error: 806 | 807 | ```php 808 | class Foo 809 | { 810 | public function bar() 811 | { 812 | return 'baz'; 813 | } 814 | } 815 | 816 | $a = new Foo(); 817 | $b = $a->baz() ?? 'fallback'; // PHP Error: Call to undefined method baz() 818 | ``` 819 | 820 | ##### Chained method 821 | 822 | When using chained methods on object and an intermediary element can't be found, null coalescing won't work and you'll get an error: 823 | 824 | ```php 825 | class Foo 826 | { 827 | public function bar() 828 | { 829 | return (object)[]; 830 | } 831 | } 832 | 833 | $a = new Foo(); 834 | $b = $a->bar()->baz() ?? 'fallback'; // PHP Error: Call to undefined method baz() 835 | ``` 836 | 837 | #### Null Coalescing Assignment operator 838 | 839 | ![php-version-74](https://shields.io/badge/php->=7.4-blue) 840 | 841 | You can set a default value to a property when it is null: 842 | 843 | ```php 844 | $a = null; 845 | $a = $a ?? 'foo'; 846 | // $a = 'foo' 847 | ``` 848 | 849 | Since PHP 7.4, you can use the null coalescing assignment operator to do the same: 850 | 851 | ```php 852 | $a = null; 853 | $a ??= 'foo'; 854 | // $a = 'foo' 855 | ``` 856 | 857 | ### Nullsafe operator 858 | 859 | ![php-version-80](https://shields.io/badge/php->=8.0-blue) 860 | 861 | When trying to read a property or calling a method on null, you'll get a warning and an error: 862 | 863 | ```php 864 | $a = null; 865 | $b = $a->foo; // PHP Warning: Attempt to read property "foo" on null 866 | // $b = null 867 | 868 | $c = $a->foo(); // PHP Error: Call to a member function foo() on null 869 | ``` 870 | 871 | With the nullsafe operator, you can do both without warning nor error: 872 | 873 | ```php 874 | $a = null; 875 | $b = $a?->foo; 876 | // $b = null 877 | $c = $a?->foo(); 878 | // $c = null 879 | ``` 880 | 881 | You can chain multiple nullsafe operators: 882 | 883 | ```php 884 | $a = null; 885 | $b = $a?->foo?->bar; 886 | // $b = null 887 | $c = $a?->foo()?->bar(); 888 | // $c = null 889 | ``` 890 | 891 | An expression is short-circuited from the first null-safe operator that encounters null: 892 | 893 | ```php 894 | $a = null; 895 | $b = $a?->foo->bar->baz(); 896 | // $b = null 897 | ``` 898 | 899 | Nullsafe operator has no effect if the target is not null: 900 | 901 | ```php 902 | $a = 'foo'; 903 | $b = $a?->bar; // PHP Warning: Attempt to read property "bar" on string 904 | // $b = null 905 | $c = $a?->baz(); // PHP Error: Call to a member function baz() on string 906 | ``` 907 | 908 | Nullsafe operator can't handle arrays properly but still can have some effect: 909 | 910 | ```php 911 | $a = []; 912 | $b = $a['foo']->bar; 913 | // PHP Warning: Undefined array key "foo" 914 | // PHP Warning: Attempt to read property "bar" on null 915 | // $b = null 916 | 917 | $c = $a['foo']?->bar; // PHP Warning: Undefined array key "foo" 918 | // $c = null 919 | 920 | $d = $a['foo']->bar(); 921 | // PHP Warning: Undefined array key "foo" 922 | // PHP Error: Call to a member function bar() on null 923 | 924 | $e = $a['foo']?->bar(); // PHP Warning: Undefined array key "foo" 925 | // $e = null 926 | ``` 927 | 928 | You cannot use the nullsafe operator to write, it is read only: 929 | 930 | ```php 931 | $a = null; 932 | $a?->foo = 'bar'; // PHP Fatal error: Can't use nullsafe operator in write context 933 | ``` 934 | 935 | ### Spread operator 936 | 937 | #### Variadic parameter 938 | 939 | ![php-version-56](https://shields.io/badge/php->=5.6-blue) 940 | 941 | Since PHP 5.6 (~ august 2014), you can add a variadic parameter to any function that let you use an argument lists with variable-length: 942 | 943 | ```php 944 | function countParameters(string $param, string ...$options): int 945 | { 946 | 947 | foreach ($options as $option) { 948 | // you can iterate on $options 949 | } 950 | 951 | return 1 + count($options); 952 | } 953 | 954 | countParameters('foo'); // 1 955 | countParameters('foo', 'bar'); // 2 956 | countParameters('foo', 'bar', 'baz'); // 3 957 | ``` 958 | 959 | Variadic parameter should always be the last parameter declared: 960 | 961 | ```php 962 | function countParameters(string ...$options, string $param) 963 | { 964 | // some code 965 | } 966 | // PHP Fatal error: Only the last parameter can be variadic 967 | ``` 968 | 969 | You can have only one variadic parameter: 970 | 971 | ```php 972 | function countParameters(string ...$options, string ...$moreOptions) 973 | { 974 | // some code 975 | } 976 | // PHP Fatal error: Only the last parameter can be variadic 977 | ``` 978 | 979 | It can't have a default value: 980 | 981 | ```php 982 | function countParameters(string $param, string ...$options = []) 983 | { 984 | // some code 985 | } 986 | // PHP Parse error: Variadic parameter cannot have a default value 987 | ``` 988 | 989 | When not typed, it accepts any value: 990 | 991 | ```php 992 | function countParameters(string $param, ...$options): int 993 | { 994 | return 1 + count($options); 995 | } 996 | 997 | $a = countParameters('foo', null, [], true); 998 | // $a = 4 999 | ``` 1000 | 1001 | When typed, you have to use properly typed values: 1002 | 1003 | ```php 1004 | function countParameters(string $param, string ...$options): int 1005 | { 1006 | return 1 + count($options); 1007 | } 1008 | 1009 | countParameters('foo', null); 1010 | // TypeError: countParameters(): Argument #2 must be of type string, null given 1011 | 1012 | countParameters('foo', []); 1013 | // TypeError: countParameters(): Argument #2 must be of type string, array given 1014 | ``` 1015 | 1016 | #### Argument unpacking 1017 | 1018 | ![php-version-56](https://shields.io/badge/php->=5.6-blue) 1019 | 1020 | Arrays and traversable objects can be unpacked into argument lists when calling functions by using the spread operator: 1021 | 1022 | ```php 1023 | function add(int $a, int $b, int $c): int 1024 | { 1025 | return $a + $b + $c; 1026 | } 1027 | $array = [2, 3]; 1028 | $r = add(1, ...$array); 1029 | 1030 | // $r = 6 1031 | ``` 1032 | 1033 | The given array can have more elements than needed: 1034 | 1035 | ```php 1036 | function add(int $a, int $b, int $c): int 1037 | { 1038 | return $a + $b + $c; 1039 | } 1040 | $array = [2, 3, 4, 5]; 1041 | $r = add(1, ...$array); 1042 | 1043 | // $r = 6 1044 | ``` 1045 | 1046 | The given array can't have lesser elements than needed: 1047 | 1048 | ```php 1049 | function add(int $a, int $b, int $c): int 1050 | { 1051 | return $a + $b + $c; 1052 | } 1053 | $array = [2]; 1054 | $r = add(1, ...$array); // TypeError: Too few arguments to function add(), 2 passed 1055 | ``` 1056 | 1057 | Except when some function arguments have a default value: 1058 | 1059 | ```php 1060 | function add(int $a, int $b, int $c = 0): int 1061 | { 1062 | return $a + $b + $c; 1063 | } 1064 | $array = [2]; 1065 | $r = add(1, ...$array); 1066 | // $r = 3 1067 | ``` 1068 | 1069 | If an argument is typed and the passed value does not match the given type, you'll get an error: 1070 | 1071 | ```php 1072 | function add(int $a, int $b, int $c): int 1073 | { 1074 | return $a + $b + $c; 1075 | } 1076 | $array = ['foo', 'bar']; 1077 | $r = add(1, ...$array); // TypeError: add(): Argument #2 ($b) must be of type int, string given 1078 | ``` 1079 | 1080 | Since PHP 8.0, it is possible to unpack an associative array (string-keyed) as it will use [named arguments](#unpacking-named-arguments). 1081 | 1082 | #### Array unpacking 1083 | 1084 | ##### Indexed array 1085 | 1086 | ![php-version-74](https://shields.io/badge/php->=7.4-blue) 1087 | 1088 | When you want to merge multiple arrays, you generally use `array_merge`: 1089 | 1090 | ```php 1091 | $array1 = ['baz']; 1092 | $array2 = ['foo', 'bar']; 1093 | 1094 | $array3 = array_merge($array1, $array2); 1095 | // $array3 = ['baz', 'foo', 'bar'] 1096 | ``` 1097 | 1098 | But since PHP 7.4, you can unpack indexed arrays, with spread operator: 1099 | 1100 | ```php 1101 | $array1 = ['foo', 'bar']; 1102 | $array2 = ['baz', ...$array1]; 1103 | // $array2 = ['baz', 'foo', 'bar'] 1104 | ``` 1105 | 1106 | Elements will be merged in the order they are passed: 1107 | 1108 | ```php 1109 | $array1 = ['foo', 'bar']; 1110 | $array2 = ['baz', ...$array1, "qux"]; 1111 | // $array2 = ['baz', 'foo', 'bar', "qux"] 1112 | ``` 1113 | 1114 | It doesn't do any deduplication: 1115 | 1116 | ```php 1117 | $array1 = ['foo', 'bar']; 1118 | $array2 = ['foo', ...$array1]; 1119 | // $array2 = ['foo', 'foo', 'bar'] 1120 | ``` 1121 | 1122 | You can unpack multiple arrays at once: 1123 | 1124 | ```php 1125 | $array1 = ['foo', 'bar']; 1126 | $array2 = ['baz']; 1127 | $array3 = [ ...$array1, ...$array2]; 1128 | // $array3 = ['foo', 'bar', 'baz'] 1129 | ``` 1130 | 1131 | You can unpack the same array multiple times: 1132 | 1133 | ```php 1134 | $array1 = ['foo', 'bar']; 1135 | $array2 = [ ...$array1, ...$array1]; 1136 | // $array2 = ['foo', 'bar', 'foo', 'bar'] 1137 | ``` 1138 | 1139 | You can unpack an empty array with no error nor warning: 1140 | 1141 | ```php 1142 | $array1 = []; 1143 | $array2 = ['foo', ...$array1]; 1144 | // $array2 = ['foo'] 1145 | ``` 1146 | 1147 | You can unpack an array that has not been previously stored in a property: 1148 | 1149 | ```php 1150 | $array1 = [...['foo', 'bar'], 'baz']; 1151 | // $array1 = ['foo', 'bar', 'baz'] 1152 | ``` 1153 | 1154 | Unpacking only works with arrays (or objects inplementing Traversable interface). If you try to unpack any other value, such as null, you'll get an error: 1155 | 1156 | ```php 1157 | $array1 = null; 1158 | $array2 = ['foo', ...$array1]; // PHP Error: Only arrays and Traversables can be unpacked 1159 | ``` 1160 | 1161 | You can unpack the result of a function/method: 1162 | 1163 | ```php 1164 | function getArray(): array 1165 | { 1166 | return ['foo', 'bar']; 1167 | } 1168 | 1169 | $array = [...getArray(), 'baz']; 1170 | // $array = ['foo', 'bar', 'baz'] 1171 | ``` 1172 | 1173 | ##### Associative array 1174 | 1175 | ![php-version-81](https://shields.io/badge/php->=8.1-blue) 1176 | 1177 | Since php 8.1, you can unpack associative array (string-keyed): 1178 | 1179 | ```php 1180 | $array1 = ['foo' => 'bar']; 1181 | $array2 = [ 1182 | 'baz' => 'qux', 1183 | ...$array1 1184 | ]; 1185 | // $array2 = ['baz' => 'qux', 'foo' => 'bar',] 1186 | ``` 1187 | 1188 | You can unpack array with an already existing key: 1189 | 1190 | ```php 1191 | $array1 = ['foo' => 'bar']; 1192 | $array2 = [ 1193 | 'foo' => 'baz', 1194 | ...$array1 1195 | ]; 1196 | // $array2 = ['foo' => 'bar',] 1197 | ``` 1198 | 1199 | You can unpack an empty array without error nor warning: 1200 | 1201 | ```php 1202 | $array1 = []; 1203 | $array2 = [ 1204 | ...$array1, 1205 | ...[] 1206 | ]; 1207 | // $array2 = [] 1208 | ``` 1209 | 1210 | ### Named arguments 1211 | 1212 | ![php-version-80](https://shields.io/badge/php->=8.0-blue) 1213 | 1214 | Since PHP 8.0, it is possible to pass in arguments by name instead of their position. 1215 | 1216 | Considering a function like this: 1217 | 1218 | ```php 1219 | function concat(string $first, string $second): string 1220 | { 1221 | return $first . ' ' . $second; 1222 | } 1223 | $a = concat('foo', 'bar'); 1224 | // $a = 'foo bar' 1225 | ``` 1226 | 1227 | You can have the same result with the named argument syntax: 1228 | 1229 | ```php 1230 | $a = concat(first: 'foo', second: 'bar'); 1231 | // $a = 'foo bar' 1232 | ``` 1233 | 1234 | You can call it with arguments in a different order: 1235 | 1236 | ```php 1237 | $a = concat(second: 'bar', first: 'foo'); 1238 | // $a = 'foo bar' 1239 | ``` 1240 | 1241 | You can skip optional parameters: 1242 | 1243 | ```php 1244 | function orGate(bool $option1 = false, bool $option2 = false, bool $option3 = false): bool 1245 | { 1246 | return $option1 || $option2 || $option3; 1247 | } 1248 | $a = orGate(option3: true); 1249 | // $a = true 1250 | ``` 1251 | 1252 | But you cannot skip a mandatory argument: 1253 | 1254 | ```php 1255 | $a = concat(second: 'bar'); 1256 | // TypeError: concat(): Argument #1 ($first) not passed 1257 | ``` 1258 | 1259 | You cannot include some extra arguments: 1260 | 1261 | ```php 1262 | $a = concat(first: 'foo', second: 'bar', third: 'baz'); 1263 | // PHP Error: Unknown named parameter $third 1264 | ``` 1265 | 1266 | Named arguments also work with object constructor: 1267 | 1268 | ```php 1269 | Class Foo 1270 | { 1271 | public function __construct( 1272 | public string $first, 1273 | public string $second 1274 | ) {} 1275 | 1276 | } 1277 | $f = new Foo(first: 'bar', second: 'baz'); 1278 | ``` 1279 | 1280 | #### Named variadics 1281 | 1282 | You can use named arguments with a variadic parameter: 1283 | 1284 | ```php 1285 | function showParams(string ...$params): array 1286 | { 1287 | return $params; 1288 | } 1289 | $a = showParams(first: 'foo', second: 'bar', third: 'baz'); 1290 | // $a = ["first" => "foo", "second" => "bar", "third" => "baz"] 1291 | ``` 1292 | 1293 | #### Unpacking named arguments 1294 | 1295 | You can unpack an associative array as named arguments if keys match arguments names: 1296 | 1297 | ```php 1298 | function add(int $a, int $b, int $c): int 1299 | { 1300 | return $a + $b + $c; 1301 | } 1302 | $array = [ 1303 | "b" => 2, 1304 | "c" => 3 1305 | ]; 1306 | $r = add(1, ...$array); 1307 | // $r = 6 1308 | ``` 1309 | 1310 | Order of the elements in the associative array doesn't matter: 1311 | 1312 | ```php 1313 | function add(int $a, int $b, int $c): int 1314 | { 1315 | return $a + $b + $c; 1316 | } 1317 | $array = [ 1318 | "c" => 3, 1319 | "b" => 2, 1320 | ]; 1321 | $r = add(1, ...$array); 1322 | // $r = 6 1323 | ``` 1324 | 1325 | If a key doesn't match an argument's name, you'll get an error: 1326 | 1327 | ```php 1328 | function add(int $a, int $b, int $c): int 1329 | { 1330 | return $a + $b + $c; 1331 | } 1332 | $array = [ 1333 | "b" => 2, 1334 | "c" => 3, 1335 | "d" => 4, 1336 | ]; 1337 | $r = add(1, ...$array); // PHP Error: Unknown named parameter $d 1338 | ``` 1339 | 1340 | #### External resource 1341 | 1342 | - [Named arguments in depth on stitcher's blog](https://stitcher.io/blog/php-8-named-arguments) 1343 | - [Named Parameters on PHP.Watch](https://php.watch/versions/8.0/named-parameters) 1344 | 1345 | ### Short closures 1346 | 1347 | ![php-version-74](https://shields.io/badge/php->=7.4-blue) 1348 | 1349 | Short closures, also called arrow functions, are an alternative way of writing [anonymous functions](https://www.php.net/manual/en/functions.anonymous.php) in a shorter syntax. The main goal of short closures is to reduce verbosity when it is possible : if there is only a single expression. 1350 | 1351 | Here is an example of a simple closure with only one expression : 1352 | 1353 | ```php 1354 | $foo = function ($bar) { 1355 | return $bar + 1; 1356 | } 1357 | $a = $foo(1); 1358 | // $a = 2 1359 | ``` 1360 | 1361 | You can write the same function with a short closure : 1362 | 1363 | ```php 1364 | $foo = fn ($bar) => $bar + 1; 1365 | $a = $foo(1); 1366 | // $a = 2 1367 | ``` 1368 | 1369 | You cannot give a name to a short closure : 1370 | 1371 | ```php 1372 | fn foo($bar) => $bar + 1; 1373 | // PHP Parse error: Syntax error, unexpected T_STRING, expecting '(' 1374 | ``` 1375 | 1376 | You can use short closure as function parameter. For example as a "callable" parameter in PHP's [array_reduce](https://www.php.net/manual/en/function.array-reduce.php): 1377 | 1378 | ```php 1379 | $myArray = [10,20,30]; 1380 | 1381 | $total = array_reduce($myArray, fn ($carry, $item) => $carry + $item, 0); 1382 | // $total = 60 1383 | ``` 1384 | 1385 | Type hinting is allowed as in a normal function : 1386 | 1387 | ```php 1388 | fn (int $foo): int => $foo; 1389 | ``` 1390 | 1391 | You don't need to use the `return` keyword as it is not allowed here : 1392 | 1393 | ```php 1394 | fn ($foo) => return $foo; 1395 | // PHP Parse error: Syntax error, unexpected T_RETURN 1396 | ``` 1397 | 1398 | #### Outer scope 1399 | 1400 | The short closure doesn't require the `use` keyword to be able to access properties from the outer scope : 1401 | 1402 | ```php 1403 | $bar = 10; 1404 | $baz = fn ($foo) => $foo + $bar; 1405 | $a = $baz(1); 1406 | //$a = 11 1407 | ``` 1408 | 1409 | The keyword `use` is not allowed : 1410 | 1411 | ```php 1412 | $bar = 10; 1413 | fn ($foo) use ($bar) => $foo + $bar; 1414 | // PHP Parse error: Syntax error, unexpected T_USE, expecting T_DOUBLE_ARROW 1415 | ``` 1416 | 1417 | You could use `$this` as in any other function : 1418 | 1419 | ```php 1420 | fn () => $this->foo + 1; 1421 | ``` 1422 | 1423 | ### Match expression 1424 | 1425 | ![php-version-80](https://shields.io/badge/php->=8.0-blue) 1426 | 1427 | Since PHP 8.0, there is a new `match` syntax similar to the `switch` syntax. As each matching case must only contain one expression, it can't be used and replace a switch statement in every situation. It is significantly shorter and easier to read though. 1428 | 1429 | The match expression always returns a value. Each condition only allows a single expression, and it immediately returns the value and will not fall-through following conditions without an explicit `break` statement: 1430 | 1431 | ```php 1432 | $foo = 'baz'; 1433 | $a = match($foo) { 1434 | 'bar' => 1, 1435 | 'baz' => 2, 1436 | 'qux' => 3, 1437 | } 1438 | // $a = 2 1439 | ``` 1440 | 1441 | It throws an exception when the value can't match: 1442 | 1443 | ```php 1444 | $foo = 'qux'; 1445 | $a = match($foo) { 1446 | 'bar' => 1, 1447 | 'baz' => 2, 1448 | } 1449 | // PHP Error: Unhandled match value of type string 1450 | ``` 1451 | 1452 | But it supports a default condition: 1453 | 1454 | ```php 1455 | $foo = 'qux'; 1456 | $a = match($foo) { 1457 | 'bar' => 1, 1458 | 'baz' => 2, 1459 | default => 3, 1460 | } 1461 | // $a = 3 1462 | ``` 1463 | 1464 | It allows multiple conditions in a single arm: 1465 | 1466 | ```php 1467 | $foo = 'bar'; 1468 | $a = match($foo) { 1469 | 'bar', 'baz' => 1, 1470 | default => 2, 1471 | } 1472 | // $a = 1 1473 | ``` 1474 | 1475 | It does strict type-safe comparison without type coercion (it's like using `===` instead of `==`): 1476 | 1477 | ```php 1478 | function showType($param) { 1479 | return match ($param) { 1480 | 1 => 'Integer', 1481 | '1' => 'String', 1482 | true => 'Boolean', 1483 | }; 1484 | } 1485 | 1486 | showType(1); // "Integer" 1487 | showType('1'); // "String" 1488 | showType(true); // "Boolean" 1489 | ``` 1490 | 1491 | #### External resource 1492 | 1493 | - [Match expression on PHP.Watch](https://php.watch/versions/8.0/match-expression) 1494 | 1495 | ### Stringable interface 1496 | 1497 | ![php-version-80](https://shields.io/badge/php->=8.0-blue) 1498 | 1499 | Since PHP 8.0, there is a new interface named `Stringable`, that indicates a class has a `__toString()` magic method. PHP automatically adds the Stringable interface to all classes that implement that method. 1500 | 1501 | ```php 1502 | interface Stringable { 1503 | public function __toString(): string; 1504 | } 1505 | ``` 1506 | 1507 | When you define a parameter with `Stringable` type, it will check that the given class implements the `Stringable` interface: 1508 | 1509 | ```php 1510 | class Foo { 1511 | public function __toString(): string { 1512 | return 'bar'; 1513 | } 1514 | } 1515 | 1516 | function myFunction(Stringable $param): string { 1517 | return (string) $param; 1518 | } 1519 | $a = myFunction(new Foo); 1520 | // $a = 'bar' 1521 | ``` 1522 | 1523 | If a given class doesn't implement `__toString()`, you'll get an error: 1524 | 1525 | ```php 1526 | class Foo { 1527 | } 1528 | 1529 | function myFunction(Stringable $param): string { 1530 | return (string) $param; 1531 | } 1532 | $a = myFunction(new Foo); 1533 | // TypeError: myFunction(): Argument #1 ($param) must be of type Stringable, Foo given 1534 | ``` 1535 | 1536 | A stringable type doesn't accept string: 1537 | 1538 | ```php 1539 | function myFunction(Stringable $param): string { 1540 | return (string) $param; 1541 | } 1542 | $a = myFunction('foo'); 1543 | // TypeError: myFunction(): Argument #1 ($param) must be of type Stringable, string given 1544 | ``` 1545 | 1546 | Of course, to accept both string and Stringable, you can use a union type: 1547 | 1548 | ```php 1549 | function myFunction(string|Stringable $param): string { 1550 | return (string) $param; 1551 | } 1552 | ``` 1553 | 1554 | ### Enums 1555 | 1556 | ![php-version-81](https://shields.io/badge/php->=8.1-blue) 1557 | 1558 | An Enum defines a new type, which has a fixed, limited number of possible legal values. 1559 | 1560 | ```php 1561 | enum Status 1562 | { 1563 | case DRAFT; 1564 | case PUBLISHED; 1565 | case ARCHIVED; 1566 | } 1567 | ``` 1568 | 1569 | In an Enum, each case definition is case-sensitive. Historically, in PHP we generally represent "constants" with uppercase to distinguish them from normal variables, so it makes sense to stick to uppercase notation for enum cases. But note that this will work fine and define 3 different cases: 1570 | 1571 | ```php 1572 | enum MyEnum 1573 | { 1574 | case FOO; 1575 | case foo; 1576 | case Foo; 1577 | } 1578 | ``` 1579 | 1580 | Now you can compare easily enums with type safe operator `===`: 1581 | 1582 | ```php 1583 | $statusA = Status::PENDING; 1584 | 1585 | if ($statusA === Status::PENDING) { 1586 | // true 1587 | } 1588 | ``` 1589 | 1590 | Also an enum behaves like a traditional PHP object: 1591 | 1592 | ```php 1593 | $statusA = Status::PENDING; 1594 | $statusB = Status::PENDING; 1595 | $statusC = Status::ARCHIVED; 1596 | 1597 | $statusA === $statusB; // true 1598 | $statusA === $statusC; // false 1599 | $statusC instanceof Status; // true 1600 | ``` 1601 | 1602 | You can use Enum to enforce types: 1603 | 1604 | ```php 1605 | function myFunction(Status $param) 1606 | { 1607 | return $param; 1608 | } 1609 | $a = myFunction(Status::DRAFT); 1610 | // $a = Status::DRAFT 1611 | $b = myFunction('foo'); // TypeError: myFunction(): Argument #1 ($param) must be of type Status, string given 1612 | ``` 1613 | 1614 | #### Enum methods 1615 | 1616 | You can define methods with an Enum : 1617 | 1618 | ```php 1619 | enum Status 1620 | { 1621 | case DRAFT; 1622 | case PUBLISHED; 1623 | 1624 | public function label(): string 1625 | { 1626 | return match($this) 1627 | { 1628 | Status::DRAFT => 'Not ready...', 1629 | Status::PUBLISHED => 'Published !', 1630 | }; 1631 | } 1632 | } 1633 | ``` 1634 | 1635 | then you can use methods on any enum instance: 1636 | 1637 | ```php 1638 | $a = Status::DRAFT; 1639 | $a->label(); // 'Not ready...' 1640 | ``` 1641 | 1642 | #### Backed values 1643 | 1644 | Sometimes you need to assign a proper value to each enum case (ex: to store it in a database, comparison, etc). You should define the type of the back value. Here is an example with a backed value defined as an `int` : 1645 | 1646 | ```php 1647 | enum HttpStatus: int 1648 | { 1649 | case OK = 200; 1650 | case NOT_FOUND = 404; 1651 | case INTERNAL_SERVER_ERROR = 500; 1652 | } 1653 | ``` 1654 | 1655 | And here is an example of a backed value defined as a `string`: 1656 | 1657 | ```php 1658 | enum Status: string 1659 | { 1660 | case DRAFT = 'draft'; 1661 | case PUBLISHED = 'published'; 1662 | } 1663 | ``` 1664 | 1665 | #### External resource 1666 | 1667 | - [Enums manual on PHP official documentation](https://www.php.net/manual/en/language.enumerations.php) 1668 | - [Enums on PHP.Watch](https://php.watch/versions/8.0/match-expression) 1669 | - [Enums style guide on stitcher's blog](https://stitcher.io/blog/php-enum-style-guide) 1670 | 1671 | ### Multiple lines string syntax 1672 | 1673 | ![php-version-73](https://shields.io/badge/php->=7.3-blue) 1674 | 1675 | When you want to define a string value that contains multiple lines, you generally use double quotes and escape line breaks: 1676 | 1677 | ```php 1678 | $string = "Hello\nWorld"; 1679 | ``` 1680 | 1681 | Since PHP 7.3, there is a new option for specifying a string value over multiple lines. By placing it between an opening identifier and a closing identifier: 1682 | 1683 | ```php 1684 | $string = << আপনি যদি এই বিষয়বস্তু পছন্দ করেন, তবে আপনি আমার সাথে যোগাযোগ করতে পারেন বা টুইটারে আমাকে অনুসরণ করতে পারেন. :+1: 7 | 8 | [![Tweet for help](https://img.shields.io/twitter/follow/smknstd?label=Tweet%20%40smknstd&style=social)](https://twitter.com/smknstd/) 9 | 10 | অনুবাদ: [S. M. Shamir Imtiaz](https://github.com/Ivanshamir) 11 | > **অনুবাদ নোট:** **কিছু শব্দ অনুবাদ করা হয়নি কারণ সেগুলি অত্যন্ত প্রযুক্তিগত এবং ভবিষ্যতের পাঠকদের জন্য শিখতে অসুবিধা হতে পারে**. 12 | 13 | ## ভূমিকা 14 | 15 | ### **মোটিভেশন** 16 | 17 | এই ডকুমেন্টটি PHP-এর জন্য কোড সহ একটি চিটশিট যা আপনি বিভিন্ন আপডেটেড প্রজেক্টগুলোতে প্রায়শই পাবেন. 18 | 19 | এই নির্দেশিকাটি আপনাকে প্রাথমিকভাবে PHP শেখানোর উদ্দেশ্যে নয়, বরং এমন ডেভেলপার যারা PHP এর বেসিক জানেন কিন্তু মডার্ণ কোডবেসগুলির সাথে পরিচিত হতে সমস্যায় পড়তে পারেন (বা উদাহরণ স্বরূপ লারাভেল বা সিমফনি শেখার জন্য বলা যাক) তাদের সাহায্য করার জন্য কারণ PHP রিসেন্ট বছরগুলোতে নতুন নতুন ফিচার এবং কনসেপ্ট নিয়ে আসছে. 20 | 21 | > **বিঃদ্রঃ:** এখানে প্রবর্তিত কনসেপ্টগুলি PHP-এর সবচেয়ে সাম্প্রতিক সংস্করণের উপর ভিত্তি করে ([PHP 8.1](https://www.php.net/releases/8.1/en.php) শেষ আপডেটের সময়) 22 | 23 | ### কমপ্লিমেন্টারী রির্সোসেস 24 | 25 | যদি আপনি কোন একটি টপিক বুঝতে সমস্যায় পড়েন, তখন আমি আপনাকে পরামর্শ দিব নিচের যেকোন একটি রিসোর্স থেকে উত্তর খুঁজে নিতে : 26 | - [Stitcher's blog](https://stitcher.io/blog) 27 | - [PHP.Watch](https://php.watch/versions) 28 | - [Exploring php 8.0](https://leanpub.com/exploringphp80) 29 | - [PHP The Right Way](https://phptherightway.com/) 30 | - [StackOverflow](https://stackoverflow.com/questions/tagged/php) 31 | 32 | ## সুচিপত্র 33 | 34 | - [মডার্ণ পিএইচপি চিটশিট](#মডার্ণ-পিএইচপি-চিটশিট) 35 | * [ভূমিকা](#ভূমিকা) 36 | + [মোটিভেশন](#মোটিভেশন) 37 | + [কমপ্লিমেন্টারী রির্সোসেস](#কমপ্লিমেন্টারী-রির্সোসেস) 38 | * [সুচিপত্র](#সুচিপত্র) 39 | * [নোশনস](#নোশনস) 40 | + [ফাংশন এর ডিফল্ট প্যারামিটার ভ্যালু ](#ফাংশন-এর-ডিফল্ট-প্যারামিটার-ভ্যালু) 41 | + [ট্রেইলিং কমা](#ট্রেইলিং-কমা) 42 | + [টাইপ ডিক্লারেশন](#টাইপ-ডিক্লারেশন) 43 | + [ডিস্ট্রাকচারিং অ্যারেস](#ডিস্ট্রাকচারিং-অ্যারেস) 44 | + [নাল কোলেসিং](#নাল-কোলেসিং) 45 | + [নালসেফ অপারেটর](#নালসেফ-অপারেটর) 46 | + [স্প্রেড অপারেটর](#স্প্রেড-অপারেটর) 47 | + [নেমড আর্গুমেন্টস](#নেমড-আর্গুমেন্টস) 48 | + [শর্ট ক্লোসার্স](#শর্ট-ক্লোসার্স) 49 | + [ম্যাচ এক্সপ্রেশন](#ম্যাচ-এক্সপ্রেশন) 50 | + [স্ট্রিংএবল ইন্টারফেস](#স্ট্রিংএবল-ইন্টারফেস) 51 | 52 | ## নোশনস 53 | 54 | ### ফাংশন এর ডিফল্ট প্যারামিটার ভ্যালু 55 | 56 | আপনি আপনার ফাংশন প্যারামিটারে ডিফল্ট মান সেট করতে পারেন: 57 | 58 | ```php 59 | function myFunction($param = 'foo') 60 | { 61 | return $param; 62 | } 63 | $a = myFunction(); 64 | // $a = 'foo' 65 | 66 | $b = myFunction('bar'); 67 | // $b = 'bar' 68 | ``` 69 | 70 | কিন্তু যদি আপনি নাল বা আনডিফাইন্ড প্রোপার্টি পাঠান, তাহলে ডিফল্ট ভ্যালু ব্যবহার হবে না: 71 | 72 | ```php 73 | function myFunction($param = 'foo') 74 | { 75 | return $param; 76 | } 77 | $a = myFunction(null); 78 | // $a = null 79 | 80 | $b = myFunction($undefined); // PHP Warning: Undefined variable $undefined 81 | // $b = null 82 | ``` 83 | 84 | ### ট্রেইলিং কমা 85 | 86 | ট্রেইলিং কমা, যা একটি আনত কমা নামেও পরিচিত, একটি কমা প্রতীক যা আইটেমগুলির তালিকার শেষ আইটেমের পরে টাইপ করা হয়। মাল্টিলাইনের সাথে ব্যবহার করার প্রধান সুবিধাগুলির মধ্যে একটি হল [ডিফ আউটপুট ক্লিনার](https://medium.com/@nikgraf/why-you-should-enforce-dangling-commas-for-multiline-statements-d034c98e36f8). 87 | 88 | #### অ্যারে 89 | 90 | আপনি অ্যারেতে ট্রেলিং কমা ব্যবহার করতে পারেন : 91 | 92 | ```php 93 | $array = [ 94 | 'foo', 95 | 'bar', 96 | ]; 97 | ``` 98 | #### গ্রুপড ইউজ স্টেটমে 99 | 100 | ![php-version-72](https://shields.io/badge/php->=7.2-blue) 101 | 102 | PHP 7.2 ভার্সন থেকে, আপনি গ্রুপড ইউজ স্টেটমেন্টে ট্রেলিং কমা ব্যবহার করতে পারেন: 103 | 104 | ```php 105 | use Symfony\Component\HttpKernel\{ 106 | Controller\ControllerResolverInterface, 107 | Exception\NotFoundHttpException, 108 | Event\PostResponseEvent, 109 | }; 110 | ``` 111 | #### ফাংশন এবং মেথড কল 112 | 113 | ![php-version-73](https://shields.io/badge/php->=7.3-blue) 114 | 115 | PHP 7.3 থেকে, আপনি ফাংশন কল করার সময় ট্রেলিং কমা ব্যবহার করতে পারেন: 116 | 117 | ```php 118 | function myFunction($foo, $bar) 119 | { 120 | return true; 121 | } 122 | $a = myFunction( 123 | 'baz', 124 | 'qux', 125 | ); 126 | ``` 127 | 128 | এবং মেথড কলের সময়: 129 | 130 | ```php 131 | $f = new Foo(); 132 | $f->myMethod( 133 | 'baz', 134 | 'qux', 135 | ); 136 | ``` 137 | #### ফাংশন প্যারামিটারস 138 | 139 | ![php-version-80](https://shields.io/badge/php->=8.0-blue) 140 | 141 | PHP 8.0 থেকে, আপনি ফাংশন প্যারামিটার ডিক্লেয়ার করার সময় ট্রেলিং কমা ব্যবহার করতে পারেন : 142 | 143 | ```php 144 | function myFunction( 145 | $foo, 146 | $bar, 147 | ) 148 | { 149 | return true; 150 | } 151 | ``` 152 | #### ক্লোজারস ইউজ স্টেটমেন্ট 153 | 154 | ![php-version-80](https://shields.io/badge/php->=8.0-blue) 155 | 156 | PHP 8.0 থেকে, আপনি ক্লোজারের ইউজ স্টেটমেন্টের সাথে ট্রেলিং কমা ব্যবহার করতে পারেন: 157 | 158 | ```php 159 | function() use ( 160 | $foo, 161 | $bar, 162 | ) 163 | { 164 | return true; 165 | } 166 | ``` 167 | 168 | ### টাইপ ডিক্লারেশন 169 | 170 | ![php-version-70](https://shields.io/badge/php->=7.0-blue) 171 | 172 | টাইপ ডিক্লারেশন এর সাথে আপনি প্রোপার্টি এর জন্য প্রত্যাশিত ডেটা টাইপ নির্দিষ্ট করতে পারেন যা রানটাইমে প্রয়োগ করা হবে। এটি অনেক ধরনের টাইপ সাপোর্ট করে যেমন স্কেলার টাইপ (int, স্ট্রিং, বুল এবং ফ্লোট) তার সাথে অ্যারে, ইটারেবল, অবজেক্ট, stdClass ইত্যাদিও 173 | 174 | আপনি একটি ফাংশনের প্যারামিটারে একটি টাইপ সেট করতে পারেন: 175 | 176 | ```php 177 | function myFunction(int $param) 178 | { 179 | return $param; 180 | } 181 | $a = myFunction(10); 182 | // $a = 10 183 | $b = myFunction('foo'); // TypeError: myFunction(): Argument #1 ($param) must be of type int, string given 184 | ``` 185 | 186 | আপনি ফাংশনে রিটার্ন টাইপ সেট করতে পারেন: 187 | 188 | ```php 189 | function myFunction(): int 190 | { 191 | return 'foo'; 192 | } 193 | $a = myFunction(); // TypeError: myFunction(): Return value must be of type int, string returned 194 | ``` 195 | 196 | যখন একটি ফাংশন কিছু রিটার্ণ করবেনা, তখন আপনি "void" টাইপ ব্যবহার করতে পারেন: 197 | 198 | ```php 199 | function myFunction(): void 200 | { 201 | return 'foo'; 202 | } 203 | // PHP Fatal error: A void function must not return a value 204 | ``` 205 | 206 | তবে এক্ষেত্রে আপনি নাল রিটার্ণ করতে পারবেননা: 207 | 208 | ```php 209 | function myFunction(): void 210 | { 211 | return null; 212 | } 213 | // PHP Fatal error: A void function must not return a value 214 | ``` 215 | 216 | যাইহোক, ফাংশন থেকে এক্সিট করার জন্য রিটার্ন ব্যবহার করা গ্রহণযোগ্য: 217 | 218 | ```php 219 | function myFunction(): void 220 | { 221 | return; 222 | } 223 | $a = myFunction(); 224 | // $a = null 225 | ``` 226 | 227 | #### ক্লাস প্রোপার্টি 228 | 229 | ![php-version-74](https://shields.io/badge/php->=7.4-blue) 230 | 231 | আপনি একটি ক্লাস প্রোপার্টিতে একটি টাইপ সেট করতে পারেন: 232 | 233 | ```php 234 | Class Foo 235 | { 236 | public int $bar; 237 | } 238 | $f = new Foo(); 239 | $f->bar = 'baz'; // TypeError: Cannot assign string to property Foo::$bar of type int 240 | ``` 241 | 242 | #### ইউনিয়ন টাইপ 243 | 244 | ![php-version-80](https://shields.io/badge/php->=8.0-blue) 245 | 246 | পিএইচপি 8.0 থেকে, আপনি "ইউনিয়ন টাইপ" ব্যবহার করতে পারেন যা একটি নয় বরং একাধিক ভিন্ন ধরণের টাইপ গ্রহণ করে: 247 | 248 | ```php 249 | function myFunction(string|int|array $param): string|int|array 250 | { 251 | return $param; 252 | } 253 | ``` 254 | 255 | এটি ক্লাস প্রোপার্টির সাথেও কাজ করে: 256 | 257 | ```php 258 | Class Foo 259 | { 260 | public string|int|array $bar; 261 | } 262 | ``` 263 | 264 | #### ইন্টারসেকশন টাইপ 265 | 266 | ![php-version-81](https://shields.io/badge/php->=8.1-blue) 267 | 268 | PHP 8.1 থেকে, আপনি "ইন্টারসেকশন টাইপ" (এটি "পিউর" নামেও পরিচিত) ব্যবহার করতে পারেন যেখানে প্রদত্ত ভ্যালু প্রতিটি টাইপের সাথে সম্পর্কিত। উদাহরণস্বরূপ এই প্যারামটিকে *Stringable* এবং *Countable* ইন্টারফেস উভয়ই বাস্তবায়ন করতে হবে: 269 | 270 | ```php 271 | function myFunction(Stringable&Countable $param): Stringable&Countable 272 | { 273 | return $param; 274 | } 275 | Class Foo 276 | { 277 | public function __toString() { 278 | return "something"; 279 | } 280 | } 281 | myFunction(new Foo()); 282 | // TypeError: myFunction(): Argument #1 ($param) must be of type Stringable&Countable, Foo given 283 | ``` 284 | 285 | এটি ক্লাস প্রোপার্টির সাথেও কাজ করে: 286 | 287 | ```php 288 | Class Foo 289 | { 290 | public Stringable&Countable $bar; 291 | } 292 | ``` 293 | 294 | ইন্টারসেকশন টাইপ শুধুমাত্র ক্লাস এবং ইন্টারফেস সমর্থন করে. স্কেলার প্রকার (স্ট্রিং, int, অ্যারে, নাল, মিক্সড, ইত্যাদি) অনুমোদিত নয়: 295 | 296 | ```php 297 | function myFunction(string&Countable $param) 298 | { 299 | return $param; 300 | } 301 | // PHP Fatal error: Type string cannot be part of an intersection type 302 | ``` 303 | 304 | ##### এক্সটারনাল রিসোর্স 305 | 306 | - [Intersection types on PHP.Watch](https://php.watch/versions/8.1/intersection-types) 307 | 308 | #### নালেবল টাইপ 309 | 310 | ![php-version-71](https://shields.io/badge/php->=7.1-blue) 311 | 312 | যখন একটি প্যারামিটারের কোন টাইপ নেই, তখন এটি নাল ভ্যালু গ্রহণ করতে পারে: 313 | 314 | ```php 315 | function myFunction($param) 316 | { 317 | return $param; 318 | } 319 | $a = myFunction(null); 320 | // $a = null 321 | ``` 322 | 323 | কিন্তু যখনি প্যারামিটারের টাইপ থাকবে, তখন এটি আর নাল ভ্যালু গ্রহণ করবে না এবং আপনি একটি এরর পাবেন: 324 | 325 | ```php 326 | function myFunction(string $param) 327 | { 328 | return $param; 329 | } 330 | $a = myFunction(null); // TypeError: myFunction(): Argument #1 ($param) must be of type string, null given 331 | ``` 332 | 333 | যদি ফাংশনের রিটার্ন টাইপ থাকে তবে এটি নাল ভ্যালুও গ্রহণ করবে না: 334 | 335 | ```php 336 | function myFunction(): string 337 | { 338 | return null; 339 | } 340 | $a = myFunction(); // TypeError: myFunction(): Return value must be of type string, null returned 341 | ``` 342 | 343 | আপনি একটি টাইপ ডিক্লেয়ার করার সময় সেটিকে স্পষ্টভাবে নালেবল করতে পারেন: 344 | 345 | ```php 346 | function myFunction(?string $param) 347 | { 348 | return $param; 349 | } 350 | $a = myFunction(null); 351 | // $a = null 352 | ``` 353 | 354 | অথবা একটি ইউনিয়ন টাইপ সঙ্গে: 355 | 356 | ```php 357 | function myFunction(string|null $param) 358 | { 359 | return $param; 360 | } 361 | $a = myFunction(null); 362 | // $a = null 363 | ``` 364 | 365 | এটি রিটার্ন টাইপের সাথেও কাজ করে: 366 | 367 | ```php 368 | function myFunction(?string $param): ?string 369 | { 370 | return $param; 371 | } 372 | // or 373 | function myFunction(string|null $param): string|null 374 | { 375 | return $param; 376 | } 377 | ``` 378 | 379 | কিন্তু ভয়েড নালেবল হতে পারে না: 380 | 381 | ```php 382 | function myFunction(): ?void 383 | { 384 | // some code 385 | } 386 | // PHP Fatal error: Void type cannot be nullable 387 | ``` 388 | 389 | অথবা 390 | 391 | ```php 392 | function myFunction(): void|null 393 | { 394 | // some code 395 | } 396 | // PHP Fatal error: Void type cannot be nullable 397 | ``` 398 | 399 | আপনি ক্লাস প্রোপার্টিতে নালেবল টাইপ সেট করতে পারেন : 400 | 401 | ```php 402 | Class Foo 403 | { 404 | public int|null $bar; 405 | } 406 | $f = new Foo(); 407 | $f->bar = null; 408 | $a = $f->bar; 409 | // $a = null 410 | ``` 411 | 412 | ### ডিস্ট্রাকচারিং অ্যারেস 413 | 414 | আপনি আলাদা ভেরিয়েবলে আলাদা এলিমেন্ট রাখতে অ্যারে ডিস্ট্রাকচার করতে পারেন. 415 | 416 | #### ইন্ডেক্সড অ্যারে 417 | 418 | ![php-version-40](https://shields.io/badge/php->=4.0-blue) 419 | 420 | এই ইনডেক্সড অ্যারে টিকে বিবেচনা করুন : 421 | 422 | ```php 423 | $array = ['foo', 'bar', 'baz']; 424 | ``` 425 | 426 | আপনি লিস্ট সিনট্যাক্স ব্যবহার করে এটিকে ডিস্ট্রাকচার করতে পারেন: 427 | 428 | ```php 429 | list($a, $b, $c) = $array; 430 | 431 | // $a = 'foo' 432 | // $b = 'bar' 433 | // $c = 'baz' 434 | ``` 435 | 436 | অথবা পিএইচপি 7.1 থেকে, শর্টহ্যান্ড সিনট্যাক্স: 437 | 438 | ```php 439 | [$a, $b, $c] = $array; 440 | 441 | // $a = 'foo' 442 | // $b = 'bar' 443 | // $c = 'baz' 444 | ``` 445 | 446 | আপনি ইলেমেণ্টস স্কিপ করতে পারেন: 447 | 448 | ```php 449 | list(, , $c) = $array; 450 | 451 | // $c = 'baz' 452 | ``` 453 | 454 | অথবা পিএইচপি 7.1 থেকে, শর্টহ্যান্ড সিনট্যাক্স: 455 | 456 | ```php 457 | [, , $c] = $array; 458 | 459 | // $c = 'baz' 460 | ``` 461 | 462 | আপনি যখন প্রদত্ত অ্যারেতে বিদ্যমান নেই এমন একটি ইনডেক্স ডেস্ট্রাক্ট করার চেষ্টা করেন, আপনি একটি ওয়ার্নিং পাবেন: 463 | 464 | ```php 465 | list($a, $b, $c, $d) = $array; // PHP Warning: Undefined array key 3 466 | 467 | // $a = 'foo' 468 | // $b = 'bar' 469 | // $c = 'baz' 470 | // $d = null; 471 | ``` 472 | 473 | #### অ্যাসোসিয়েটিভ অ্যারে 474 | 475 | ![php-version-71](https://shields.io/badge/php->=7.1-blue) 476 | 477 | একটি অ্যাসোসিয়েটিভ অ্যারে বিবেচনা করুন (স্ট্রিং-কীড এর মত) : 478 | 479 | ```php 480 | $array = [ 481 | 'foo' => 'value1', 482 | 'bar' => 'value2', 483 | 'baz' => 'value3', 484 | ]; 485 | ``` 486 | 487 | পূর্ববর্তী লিস্ট সিনট্যাক্স অ্যাসোসিয়েটিভ অ্যারের সাথে কাজ করবে না এবং এক্ষেত্রে আপনি একটি ওয়ার্নিং পাবেন: 488 | 489 | ```php 490 | list($a, $b, $c) = $array; // PHP Warning: Undefined array key 0 ... 491 | 492 | // $a = null 493 | // $b = null 494 | // $c = null 495 | ``` 496 | 497 | কিন্তু PHP 7.1 থেকে, আপনি কীগুলির উপর ভিত্তি করে অন্য সিনট্যাক্স দিয়ে এটি ডেস্ট্রাক্ট করতে পারেন: 498 | 499 | ```php 500 | list('foo' => $a, 'bar' => $b, 'baz' => $c) = $array; 501 | 502 | // $a = 'value1' 503 | // $b = 'value2' 504 | // $c = 'value3' 505 | ``` 506 | 507 | অথবা শর্টহ্যান্ড সিনট্যাক্স: 508 | 509 | ```php 510 | ['foo' => $a, 'bar' => $b, 'baz' => $c] = $array; 511 | 512 | // $a = 'value1' 513 | // $b = 'value2' 514 | // $c = 'value3' 515 | ``` 516 | 517 | আপনি অ্যারের শুধুমাত্র একটি অংশ ডেস্ট্রাক্ট করতে পারেন (এখানে অর্ডার কোন ব্যাপার না): 518 | 519 | ```php 520 | ['baz' => $c, 'foo' => $a] = $array; 521 | 522 | // $a = 'value1' 523 | // $c = 'value3' 524 | ``` 525 | 526 | আপনি প্রদত্ত অ্যারেতে বিদ্যমান নেই এমন একটি কী ডেস্ট্রাক্ট করার চেষ্টা করলে, আপনি একটি ওয়ার্নিং পাবেন: 527 | 528 | ```php 529 | list('moe' => $d) = $array; // PHP Warning: Undefined array key "moe" 530 | 531 | // $d = null 532 | ``` 533 | 534 | ### নাল কোলেসিং 535 | 536 | ![php-version-70](https://shields.io/badge/php->=7.0-blue) 537 | 538 | PHP 7.0 থেকে, আপনি একটি ফলব্যাক প্রোভাইড করতে নাল কোলেসিং অপারেটর ব্যবহার করতে পারেন যখন কোনো প্রোপার্টি কোনো এরর বা ওয়ার্নিং ছাড়াই নাল থাকে: 539 | 540 | ```php 541 | $a = null; 542 | $b = $a ?? 'fallback'; 543 | 544 | // $b = 'fallback' 545 | ``` 546 | 547 | এর সমতুল্য: 548 | 549 | ```php 550 | $a = null; 551 | $b = isset($a) ? $a : 'fallback'; 552 | // $b = 'fallback' 553 | ``` 554 | 555 | প্রোপার্টি আনডিফাইন্ড হলেও এটি কাজ করে: 556 | 557 | ```php 558 | $a = $undefined ?? 'fallback'; 559 | 560 | // $a = 'fallback' 561 | ``` 562 | 563 | প্রোপার্টির অন্য ভ্যালুগুলো ফলব্যাক ট্রিগার করবে না: 564 | 565 | ```php 566 | '' ?? 'fallback'; // '' 567 | 0 ?? 'fallback'; // 0 568 | false ?? 'fallback'; // false 569 | ``` 570 | 571 | আপনি একাধিকবার নাল কোলেসিং চেইন করতে পারেন: 572 | 573 | ```php 574 | $a = null; 575 | $b = null; 576 | $c = $a ?? $b ?? 'fallback'; 577 | // $c = 'fallback' 578 | ``` 579 | 580 | #### এলভিস অপারেটর 581 | 582 | ![php-version-53](https://shields.io/badge/php->=5.3-blue) 583 | 584 | এটিকে শর্টহ্যান্ড টারনারি অপারেটর (ওরফে এলভিস অপারেটর) এর সাথে বিভ্রান্ত হওয়া উচিত নয়, যা পিএইচপি 5.3 এ এসেছিল: 585 | 586 | ```php 587 | $a = null; 588 | $b = $a ?: 'fallback'; 589 | 590 | // $b = 'fallback' 591 | ``` 592 | 593 | শর্টহ্যান্ড টারনারি অপারেটর এর সমতুল্য: 594 | 595 | ```php 596 | $a = null; 597 | $b = $a ? $a : 'fallback'; 598 | // $b = 'fallback' 599 | ``` 600 | 601 | নাল কোলেসিং এবং এলভিস অপারেটরের মধ্যে ফলাফল একই রকম হতে পারে তবে কিছু নির্দিষ্ট মানের জন্য ভিন্ন: 602 | 603 | ```php 604 | '' ?: 'fallback'; // 'fallback' 605 | 0 ?: 'fallback'; // 'fallback' 606 | false ?: 'fallback'; // 'fallback' 607 | ``` 608 | 609 | #### অ্যারেতে নাল কোলেসিং 610 | 611 | যদি অ্যারে কী বিদ্যমান থাকে, তাহলে ফলব্যাক ট্রিগার করা হবে না: 612 | 613 | ```php 614 | $a = ['foo' => 'bar']; 615 | $b = $a['foo'] ?? 'fallback'; 616 | 617 | // $b = 'bar' 618 | ``` 619 | 620 | কিন্তু যখন অ্যারে বিদ্যমান থাকে না, তখন কোনো এরর বা ওয়ার্নিং ছাড়াই ফলব্যাক ট্রিগার হয়: 621 | 622 | ```php 623 | $a = null; 624 | $b = $a['foo'] ?? 'fallback'; 625 | 626 | // $b = 'fallback' 627 | ``` 628 | 629 | অথবা অ্যারে প্রোপার্ট আনডিফাইন্ড হলে, ফলব্যাক কোন ত্রুটি বা সতর্কতা ছাড়াই ট্রিগার হবে: 630 | 631 | ```php 632 | $b = $undefined['foo'] ?? 'fallback'; 633 | 634 | // $b = 'fallback' 635 | ``` 636 | 637 | যখন অ্যারে বিদ্যমান থাকে কিন্তু প্রদত্ত অ্যারেতে কী খুঁজে পাওয়া যায় না, তখন কোনো এরর বা ওয়ার্নিং ছাড়াই ফলব্যাক ট্রিগার হয়: 638 | 639 | ```php 640 | $a = []; 641 | $b = $a['foo'] ?? 'fallback'; 642 | 643 | // $b = 'fallback' 644 | ``` 645 | 646 | এটি ইন্ডেক্সড অ্যারের সাথেও কাজ করে: 647 | 648 | ```php 649 | $a = ['foo']; 650 | 651 | // reminder: $a[0] = 'foo' 652 | 653 | $b = $a[1] ?? 'fallback'; 654 | 655 | // $b = 'fallback' 656 | ``` 657 | 658 | এটি নেস্টেড অ্যারের সাথেও কাজ করে। নেস্টেড অ্যারেতে কী বিদ্যমান থাকলে, ফলব্যাক ট্রিগার হবেনা : 659 | 660 | ```php 661 | $a = [ 662 | 'foo' => [ 663 | 'bar' => 'baz' 664 | ] 665 | ]; 666 | $b = $a['foo']['bar'] ?? 'fallback'; 667 | 668 | // $b = 'baz' 669 | ``` 670 | 671 | কিন্তু যখন প্রদত্ত অ্যারেতে নেস্টেড কী পাওয়া যায় না, তখন ফলব্যাক কোনো এরর বা ওয়ার্নিং ছাড়াই ট্রিগার হয়: 672 | 673 | ```php 674 | $a = [ 675 | 'foo' => [ 676 | 'bar' => 'baz' 677 | ] 678 | ]; 679 | $b = $a['foo']['qux'] ?? 'fallback'; 680 | 681 | // $b = 'fallback' 682 | ``` 683 | 684 | #### অবজেক্টের উপর নাল কোলেসিং 685 | 686 | আপনি অবজেক্টের সাথে নাল কোলেসিং অপারেটরও ব্যবহার করতে পারেন. 687 | 688 | ##### অব্জেক্ট'স অ্যাট্রিবিউট 689 | 690 | যদি অব্জেক্ট'স অ্যাট্রিবিউট বিদ্যমান থাকে, তাহলে ফলব্যাক ট্রিগার হবেনা: 691 | 692 | ```php 693 | $a = (object)[ 694 | 'foo' => 'bar' 695 | ]; 696 | $b = $a->foo ?? 'fallback'; 697 | 698 | // $b = 'bar' 699 | ``` 700 | 701 | কিন্তু যখন অবজেক্টের অ্যাট্রিবিউট খুঁজে পাওয়া যায় না, ফলব্যাক কোনো এরর বা ওয়ার্নিং ছাড়াই ট্রিগার হয়: 702 | 703 | ```php 704 | $a = (object)[ 705 | 'foo' => 'bar' 706 | ]; 707 | $b = $a->baz ?? 'fallback'; 708 | 709 | // $b = 'fallback' 710 | ``` 711 | 712 | ##### অবজেক্টের মেথড 713 | 714 | আপনি একটি অবজেক্টের মেথডকে কল করার সময় নাল কোলেসিং অপারেটর ব্যবহার করতে পারেন। যদি প্রদত্ত মেথড বিদ্যমান থাকে, তাহলে ফলব্যাক ট্রিগার হয় না: 715 | 716 | ```php 717 | class Foo 718 | { 719 | public function bar() 720 | { 721 | return 'baz'; 722 | } 723 | } 724 | 725 | $a = new Foo(); 726 | $b = $a->bar() ?? 'fallback'; 727 | 728 | // $b = 'baz' 729 | ``` 730 | 731 | কিন্তু যখন অবজেক্টের মেথড নাল রিটার্ন করে, ফলব্যাক কোন এরর বা ওয়ার্নিং ছাড়াই ট্রিগার হয়: 732 | 733 | ```php 734 | class Foo 735 | { 736 | public function bar() 737 | { 738 | return null; 739 | } 740 | } 741 | 742 | $a = new Foo(); 743 | $b = $a->bar() ?? 'fallback'; 744 | 745 | // $b = 'fallback' 746 | ``` 747 | 748 | কিন্তু যদি অবজেক্টের মেথড নাল রিটার্ন করে, তবে ফলব্যাক কোন এরর বা ওয়ার্নিং ছাড়াই ট্রিগার হবে : 749 | 750 | ```php 751 | class Foo 752 | { 753 | public function bar() 754 | { 755 | return 'baz'; 756 | } 757 | } 758 | 759 | $a = new Foo(); 760 | $b = $a->baz() ?? 'fallback'; // PHP Error: Call to undefined method baz() 761 | ``` 762 | 763 | ##### চেইনড মেথড 764 | 765 | যখন অবজেক্টের উপর চেইনড মেথড ব্যবহার করা হয় এবং একটি মধ্যস্থতাকারী এলিমেন্ট খুঁজে পাওয়া যায় না, তখন নাল কোলেসিং কাজ করবে না এবং আপনি একটি এরর পাবেন : 766 | 767 | ```php 768 | class Foo 769 | { 770 | public function bar() 771 | { 772 | return (object)[]; 773 | } 774 | } 775 | 776 | $a = new Foo(); 777 | $b = $a->bar()->baz() ?? 'fallback'; // PHP Error: Call to undefined method baz() 778 | ``` 779 | 780 | #### নাল কোলেসিং অ্যাসাইনমেন্ট অপারেটর 781 | 782 | ![php-version-74](https://shields.io/badge/php->=7.4-blue) 783 | 784 | আপনি একটি ডিফল্ট মান সেট করতে পারেন প্রোপার্টিতে, যখন এটি নাল হয়: 785 | 786 | ```php 787 | $a = null; 788 | $a = $a ?? 'foo'; 789 | // $a = 'foo' 790 | ``` 791 | 792 | পিএইচপি 7.4 থেকে, আপনি একই কাজ করতে নাল কোলেসিং অ্যাসাইনমেন্ট অপারেটর ব্যবহার করতে পারেন: 793 | 794 | ```php 795 | $a = null; 796 | $a ??= 'foo'; 797 | // $a = 'foo' 798 | ``` 799 | 800 | ### নালসেফ অপারেটর 801 | 802 | ![php-version-80](https://shields.io/badge/php->=8.0-blue) 803 | 804 | প্রোপার্টি রিড করার সময় বা নাল পদ্ধতিতে কল করার সময়, আপনি একটি ওয়ার্নিং এবং একটি এরর পাবেন: 805 | 806 | ```php 807 | $a = null; 808 | $b = $a->foo; // PHP Warning: Attempt to read property "foo" on null 809 | // $b = null 810 | 811 | $c = $a->foo(); // PHP Error: Call to a member function foo() on null 812 | ``` 813 | 814 | নালসেফ অপারেটর দিয়ে, আপনি ওয়ার্নিং বা এরর ছাড়াই উভয়ই করতে পারেন: 815 | 816 | ```php 817 | $a = null; 818 | $b = $a?->foo; 819 | // $b = null 820 | $c = $a?->foo(); 821 | // $c = null 822 | ``` 823 | 824 | আপনি একাধিক নালসেফ অপারেটর চেইন করতে পারেন: 825 | 826 | ```php 827 | $a = null; 828 | $b = $a?->foo?->bar; 829 | // $b = null 830 | $c = $a?->foo()?->bar(); 831 | // $c = null 832 | ``` 833 | 834 | একটি এক্সপ্রেশন শর্ট এক্সিকিউট হবে যদি তা প্রথম নালসেফ অপারেটরই নাল পায়: 835 | 836 | ```php 837 | $a = null; 838 | $b = $a?->foo->bar->baz(); 839 | // $b = null 840 | ``` 841 | 842 | টার্গেট নাল না হলে নালসেফ অপারেটরের কোন প্রভাব নেই: 843 | 844 | ```php 845 | $a = 'foo'; 846 | $b = $a?->bar; // PHP Warning: Attempt to read property "bar" on string 847 | // $b = null 848 | $c = $a?->baz(); // PHP Error: Call to a member function baz() on string 849 | ``` 850 | 851 | নালসেফ অপারেটর অ্যারেকে সঠিকভাবে হ্যান্ডেল করতে পারে না তবে কিছু প্রভাব ফেলতে পারে: 852 | 853 | ```php 854 | $a = []; 855 | $b = $a['foo']->bar; 856 | // PHP Warning: Undefined array key "foo" 857 | // PHP Warning: Attempt to read property "bar" on null 858 | // $b = null 859 | 860 | $c = $a['foo']?->bar; // PHP Warning: Undefined array key "foo" 861 | // $c = null 862 | 863 | $d = $a['foo']->bar(); 864 | // PHP Warning: Undefined array key "foo" 865 | // PHP Error: Call to a member function bar() on null 866 | 867 | $e = $a['foo']?->bar(); // PHP Warning: Undefined array key "foo" 868 | // $e = null 869 | ``` 870 | 871 | আপনি রাইট করার জন্য নালসেফ অপারেটর ব্যবহার করতে পারবেন না, এটি শুধুমাত্র রিডের জন্য: 872 | 873 | ```php 874 | $a = null; 875 | $a?->foo = 'bar'; // PHP Fatal error: Can't use nullsafe operator in write context 876 | ``` 877 | 878 | ### স্প্রেড অপারেটর 879 | 880 | #### ভেরিয়াডিক প্যারামিটার 881 | 882 | ![php-version-56](https://shields.io/badge/php->=5.6-blue) 883 | 884 | PHP 5.6 (~ aug ২০১৪) থেকে, আপনি যেকোন ফাংশনে ভেরিয়াডিক প্যারামিটার যোগ করতে পারেন যাতে আপনি ভেরিয়েবল-লেংথ সহ একটি আর্গুমেন্ট লিস্ট ব্যবহার করতে পারেন : 885 | 886 | ```php 887 | function countParameters(string $param, string ...$options): int 888 | { 889 | 890 | foreach ($options as $option) { 891 | // you can iterate on $options 892 | } 893 | 894 | return 1 + count($options); 895 | } 896 | 897 | countParameters('foo'); // 1 898 | countParameters('foo', 'bar'); // 2 899 | countParameters('foo', 'bar', 'baz'); // 3 900 | ``` 901 | 902 | ভ্যারিয়াডিক প্যারামিটার সর্বদা শেষ প্যারামিটারে হওয়া উচিত: 903 | 904 | ```php 905 | function countParameters(string ...$options, string $param) 906 | { 907 | // some code 908 | } 909 | // PHP Fatal error: Only the last parameter can be variadic 910 | ``` 911 | 912 | আপনি শুধুমাত্র একটি ভ্যারিয়াডিক প্যারামিটার ব্যাবহার করতে পারেন: 913 | 914 | ```php 915 | function countParameters(string ...$options, string ...$moreOptions) 916 | { 917 | // some code 918 | } 919 | // PHP Fatal error: Only the last parameter can be variadic 920 | ``` 921 | 922 | এটির ডিফল্ট মান থাকতে পারে না : 923 | 924 | ```php 925 | function countParameters(string $param, string ...$options = []) 926 | { 927 | // some code 928 | } 929 | // PHP Parse error: Variadic parameter cannot have a default value 930 | ``` 931 | 932 | টাইপ বলা না হলে, এটি যে কোনো মান গ্রহণ করে: 933 | 934 | ```php 935 | function countParameters(string $param, ...$options): int 936 | { 937 | return 1 + count($options); 938 | } 939 | 940 | $a = countParameters('foo', null, [], true); 941 | // $a = 4 942 | ``` 943 | 944 | টাইপ বলা হলে, আপনাকে সঠিকভাবে টাইপড ভ্যালুস ব্যবহার করতে হবে: 945 | 946 | ```php 947 | function countParameters(string $param, string ...$options): int 948 | { 949 | return 1 + count($options); 950 | } 951 | 952 | countParameters('foo', null); 953 | // TypeError: countParameters(): Argument #2 must be of type string, null given 954 | 955 | countParameters('foo', []); 956 | // TypeError: countParameters(): Argument #2 must be of type string, array given 957 | ``` 958 | 959 | #### আর্গুমেন্ট আনপ্যাকিং 960 | 961 | ![php-version-56](https://shields.io/badge/php->=5.6-blue) 962 | 963 | স্প্রেড অপারেটর ব্যবহার করে ফাংশন কল করার সময় অ্যারে এবং ট্রাভার্সেবল অবজেক্টগুলি আর্গুমেন্ট লিস্টে আনপ্যাক করা যেতে পারে: 964 | 965 | ```php 966 | function add(int $a, int $b, int $c): int 967 | { 968 | return $a + $b + $c; 969 | } 970 | $array = [2, 3]; 971 | $r = add(1, ...$array); 972 | 973 | // $r = 6 974 | ``` 975 | 976 | প্রদত্ত অ্যারেতে প্রয়োজনের চেয়ে বেশি এলিমেন্ট থাকতে পারে: 977 | 978 | ```php 979 | function add(int $a, int $b, int $c): int 980 | { 981 | return $a + $b + $c; 982 | } 983 | $array = [2, 3, 4, 5]; 984 | $r = add(1, ...$array); 985 | 986 | // $r = 6 987 | ``` 988 | 989 | প্রদত্ত অ্যারেতে প্রয়োজনের চেয়ে কম উপাদান থাকতে পারবে না: 990 | 991 | ```php 992 | function add(int $a, int $b, int $c): int 993 | { 994 | return $a + $b + $c; 995 | } 996 | $array = [2]; 997 | $r = add(1, ...$array); // TypeError: Too few arguments to function add(), 2 passed 998 | ``` 999 | 1000 | যদি না কিছু ফাংশন আর্গুমেন্টের একটি ডিফল্ট মান থাকে: 1001 | 1002 | ```php 1003 | function add(int $a, int $b, int $c = 0): int 1004 | { 1005 | return $a + $b + $c; 1006 | } 1007 | $array = [2]; 1008 | $r = add(1, ...$array); 1009 | // $r = 3 1010 | ``` 1011 | 1012 | যদি একটি আর্গুমেন্ট টাইপড হয় এবং পাস করা ভ্যালু প্রদত্ত টাইপের সাথে মেলে না, তাহলে আপনি একটি এরর পাবেন: 1013 | 1014 | ```php 1015 | function add(int $a, int $b, int $c): int 1016 | { 1017 | return $a + $b + $c; 1018 | } 1019 | $array = ['foo', 'bar']; 1020 | $r = add(1, ...$array); // TypeError: add(): Argument #2 ($b) must be of type int, string given 1021 | ``` 1022 | 1023 | পিএইচপি ৮.০ থেকে, এটি একটি অ্যাসোসিয়েটিভ অ্যারে (স্ট্রিং-কীড) হিসেবে আনপ্যাক করা সম্ভব কারণ এটি [নামযুক্ত আর্গুমেন্ট](#unpacking-named-arguments) ব্যবহার করে . 1024 | 1025 | #### অ্যারে আনপ্যাকিং 1026 | 1027 | ##### ইন্ডেক্সড অ্যারে 1028 | 1029 | ![php-version-74](https://shields.io/badge/php->=7.4-blue) 1030 | 1031 | আপনি যখন একাধিক অ্যারে মার্জ করতে চান, আপনি সাধারণত ব্যবহার করেন `array_merge`: 1032 | 1033 | ```php 1034 | $array1 = ['baz']; 1035 | $array2 = ['foo', 'bar']; 1036 | 1037 | $array3 = array_merge($array1,$array2); 1038 | // $array3 = ['baz', 'foo', 'bar'] 1039 | ``` 1040 | 1041 | কিন্তু PHP 7.4 থেকে, আপনি স্প্রেড অপারেটরের সাথে ইনডেক্সড অ্যারে আনপ্যাক করতে পারেন: 1042 | 1043 | ```php 1044 | $array1 = ['foo', 'bar']; 1045 | $array2 = ['baz', ...$array1]; 1046 | // $array2 = ['baz', 'foo', 'bar'] 1047 | ``` 1048 | 1049 | এলিমেন্টগুলি যে ক্রমে পাস করা হবে সেভাবে মার্জ করা হবে: 1050 | 1051 | ```php 1052 | $array1 = ['foo', 'bar']; 1053 | $array2 = ['baz', ...$array1, "qux"]; 1054 | // $array2 = ['baz', 'foo', 'bar', "qux"] 1055 | ``` 1056 | 1057 | এটি কোনো অনুলিপি করে না: 1058 | 1059 | ```php 1060 | $array1 = ['foo', 'bar']; 1061 | $array2 = ['foo', ...$array1]; 1062 | // $array2 = ['foo', 'foo', 'bar'] 1063 | ``` 1064 | 1065 | আপনি একবারে একাধিক অ্যারে আনপ্যাক করতে পারেন: 1066 | 1067 | ```php 1068 | $array1 = ['foo', 'bar']; 1069 | $array2 = ['baz']; 1070 | $array3 = [ ...$array1, ...$array2]; 1071 | // $array3 = ['foo', 'bar', 'baz'] 1072 | ``` 1073 | 1074 | আপনি একই অ্যারে একাধিকবার আনপ্যাক করতে পারেন: 1075 | 1076 | ```php 1077 | $array1 = ['foo', 'bar']; 1078 | $array2 = [ ...$array1, ...$array1]; 1079 | // $array2 = ['foo', 'bar', 'foo', 'bar'] 1080 | ``` 1081 | 1082 | আপনি কোনও এরর বা ওয়ার্নিং ছাড়াই একটি এম্পটি অ্যারে আনপ্যাক করতে পারেন: 1083 | 1084 | ```php 1085 | $array1 = []; 1086 | $array2 = ['foo', ...$array1]; 1087 | // $array2 = ['foo'] 1088 | ``` 1089 | 1090 | আপনি একটি অ্যারে আনপ্যাক করতে পারেন যা পূর্বে একটি প্রোপার্টিতেও রাখা হয়নি: 1091 | 1092 | ```php 1093 | $array1 = [...['foo', 'bar'], 'baz']; 1094 | // $array1 = ['foo', 'bar', 'baz'] 1095 | ``` 1096 | 1097 | আনপ্যাকিং শুধুমাত্র অ্যারের সাথে কাজ করে (অথবা ট্রাভার্সেবল ইন্টারফেসের অবজেক্টের সাথে)। আপনি যদি অন্য কোনো ভ্যালু আনপ্যাক করার চেষ্টা করেন, যেমন নাল, আপনি এরর পাবেন: 1098 | 1099 | ```php 1100 | $array1 = null; 1101 | $array2 = ['foo', ...$array1]; // PHP Error: Only arrays and Traversables can be unpacked 1102 | ``` 1103 | 1104 | আপনি একটি ফাংশন/মেথডের রেজাল্ট আনপ্যাক করতে পারেন: 1105 | 1106 | ```php 1107 | function getArray(): array 1108 | { 1109 | return ['foo', 'bar']; 1110 | } 1111 | 1112 | $array = [...getArray(), 'baz']; 1113 | // $array = ['foo', 'bar', 'baz'] 1114 | ``` 1115 | 1116 | ##### অ্যাসোসিয়েটিভ অ্যারে 1117 | 1118 | ![php-version-81](https://shields.io/badge/php->=8.1-blue) 1119 | 1120 | php 8.1 থেকে, আপনি অ্যাসোসিয়েটিভ অ্যারে আনপ্যাক করতে পারেন (স্ট্রিং-কীড): 1121 | 1122 | ```php 1123 | $array1 = ['foo' => 'bar']; 1124 | $array2 = [ 1125 | 'baz' => 'qux', 1126 | ...$array1 1127 | ]; 1128 | // $array2 = ['baz' => 'qux', 'foo' => 'bar',] 1129 | ``` 1130 | 1131 | আপনি ইতিমধ্যে বিদ্যমান কী দিয়ে অ্যারে আনপ্যাক করতে পারেন: 1132 | 1133 | ```php 1134 | $array1 = ['foo' => 'bar']; 1135 | $array2 = [ 1136 | 'foo' => 'baz', 1137 | ...$array1 1138 | ]; 1139 | // $array2 = ['foo' => 'bar',] 1140 | ``` 1141 | 1142 | আপনি এরর বা ওয়ার্নিং ছাড়াই একটি খালি অ্যারে আনপ্যাক করতে পারেন: 1143 | 1144 | ```php 1145 | $array1 = []; 1146 | $array2 = [ 1147 | ...$array1, 1148 | ...[] 1149 | ]; 1150 | // $array2 = [] 1151 | ``` 1152 | 1153 | ### নেমড আর্গুমেন্টস 1154 | 1155 | ![php-version-80](https://shields.io/badge/php->=8.0-blue) 1156 | 1157 | PHP 8.0 থেকে, অবস্থানের পরিবর্তে নাম দিয়ে আর্গুমেন্টে পাস করা সম্ভব. 1158 | 1159 | এই ফাংশনটি বিবেচনা করুন: 1160 | 1161 | ```php 1162 | function concat(string $first, string $second): string 1163 | { 1164 | return $first . ' ' . $second; 1165 | } 1166 | $a = concat('foo', 'bar'); 1167 | // $a = 'foo bar' 1168 | ``` 1169 | 1170 | আপনি নামযুক্ত আর্গুমেন্ট সিনট্যাক্সের থেকেও একই ফলাফল পেতে পারেন: 1171 | 1172 | ```php 1173 | $a = concat(first: 'foo', second: 'bar'); 1174 | // $a = 'foo bar' 1175 | ``` 1176 | 1177 | আপনি এটিকে ভিন্ন ক্রমে আর্গুমেন্ট সহ কল করতে পারেন: 1178 | 1179 | ```php 1180 | $a = concat(second: 'bar', first: 'foo'); 1181 | // $a = 'foo bar' 1182 | ``` 1183 | 1184 | আপনি অপশনাল প্যারামিটার এড়িয়ে যেতে পারেন: 1185 | 1186 | ```php 1187 | function orGate(bool $option1 = false, bool $option2 = false, bool $option3 = false): bool 1188 | { 1189 | return $option1 || $option2 || $option3; 1190 | } 1191 | $a = orGate(option3: true); 1192 | // $a = true 1193 | ``` 1194 | 1195 | কিন্তু আপনি অত্যাবশ্যকীয় আর্গুমেন্ট এড়িয়ে যেতে পারবেন না: 1196 | 1197 | ```php 1198 | $a = concat(second: 'bar'); 1199 | // TypeError: concat(): Argument #1 ($first) not passed 1200 | ``` 1201 | 1202 | আপনি অতিরিক্ত আর্গুমেন্ট অন্তর্ভুক্ত করতে পারবেন না: 1203 | 1204 | ```php 1205 | $a = concat(first: 'foo', second: 'bar', third: 'baz'); 1206 | // PHP Error: Unknown named parameter $third 1207 | ``` 1208 | 1209 | নামযুক্ত আর্গুমেন্ট অবজেক্ট কনস্ট্রাক্টরের সাথেও কাজ করে: 1210 | 1211 | ```php 1212 | Class Foo 1213 | { 1214 | public function __construct( 1215 | public string $first, 1216 | public string $second 1217 | ) {} 1218 | 1219 | } 1220 | $f = new Foo(first: 'bar', second: 'baz'); 1221 | ``` 1222 | 1223 | #### নেমড ভেরিয়াডিকস 1224 | 1225 | আপনি ভেরিয়াডিক প্যারামিটার সহ নামযুক্ত আর্গুমেন্ট ব্যবহার করতে পারেন: 1226 | 1227 | ```php 1228 | function showParams(string ...$params): array 1229 | { 1230 | return $params; 1231 | } 1232 | $a = showParams(first: 'foo', second: 'bar', third: 'baz'); 1233 | // $a = ["first" => "foo", "second" => "bar", "third" => "baz"] 1234 | ``` 1235 | 1236 | #### আনপ্যাকিং নেমড আর্গুমেন্টস 1237 | 1238 | আপনি নামযুক্ত আর্গুমেন্ট হিসাবে একটি আসোসিয়েটিভ অ্যারে আনপ্যাক করতে পারেন যদি কীগুলি আর্গুমেন্টের নামের সাথে মেলে: 1239 | 1240 | ```php 1241 | function add(int $a, int $b, int $c): int 1242 | { 1243 | return $a + $b + $c; 1244 | } 1245 | $array = [ 1246 | "b" => 2, 1247 | "c" => 3 1248 | ]; 1249 | $r = add(1, ...$array); 1250 | // $r = 6 1251 | ``` 1252 | 1253 | অ্যাসোসিয়েটিভ অ্যারের উপাদানগুলির ক্ষেত্রে ক্রম কোন ব্যাপার নয়: 1254 | 1255 | ```php 1256 | function add(int $a, int $b, int $c): int 1257 | { 1258 | return $a + $b + $c; 1259 | } 1260 | $array = [ 1261 | "c" => 3, 1262 | "b" => 2, 1263 | ]; 1264 | $r = add(1, ...$array); 1265 | // $r = 6 1266 | ``` 1267 | 1268 | যদি একটি কী একটি আর্গুমেন্টের নামের সাথে না মেলে, তাহলে আপনি এরর পাবেন: 1269 | 1270 | ```php 1271 | function add(int $a, int $b, int $c): int 1272 | { 1273 | return $a + $b + $c; 1274 | } 1275 | $array = [ 1276 | "b" => 2, 1277 | "c" => 3, 1278 | "d" => 4, 1279 | ]; 1280 | $r = add(1, ...$array); // PHP Error: Unknown named parameter $d 1281 | ``` 1282 | 1283 | #### এক্সটারনাল রিসোর্স 1284 | 1285 | - [Named arguments in depth on stitcher's blof](https://stitcher.io/blog/php-8-named-arguments) 1286 | - [Named Parameters on PHP.Watch](https://php.watch/versions/8.0/named-parameters) 1287 | 1288 | ### শর্ট ক্লোজার্স 1289 | 1290 | ![php-version-74](https://shields.io/badge/php->=7.4-blue) 1291 | 1292 | শর্ট ক্লোজার, যাকে অ্যারো ফাংশনও বলা হয়, একটি সংক্ষিপ্ত সিনট্যাক্স গঠনে [অ্যানোনিমাস ফাংশন](https://www.php.net/manual/en/functions.anonymous.php) লেখার একটি বিকল্প উপায়। শর্ট ক্লোজারের মূল লক্ষ্য হল শব্দচয় কমানো, যদি সম্ভব হয়: যদি শুধুমাত্র একটি সিঙ্গেল এক্সপ্রেশন থাকে. 1293 | 1294 | এখানে শুধুমাত্র একটি এক্সপ্রেশন সহ একটি সিম্পল ক্লোজারের একটি উদাহরণ দেয়া হয়েছে : 1295 | 1296 | ```php 1297 | $foo = function ($bar) { 1298 | return $bar + 1; 1299 | } 1300 | $a = $foo(1); 1301 | // $a = 2 1302 | ``` 1303 | 1304 | আপনি শর্ট ক্লোজার দিয়ে একই ফাংশন লিখতে পারেন : 1305 | 1306 | ```php 1307 | $foo = fn ($bar) => $bar + 1; 1308 | $a = $foo(1); 1309 | // $a = 2 1310 | ``` 1311 | 1312 | আপনি শর্ট ক্লোজারের কোন নাম দিতে পারবেন না : 1313 | 1314 | ```php 1315 | fn foo($bar) => $bar + 1; 1316 | // PHP Parse error: Syntax error, unexpected T_STRING, expecting '(' 1317 | ``` 1318 | 1319 | আপনি ফাংশন প্যারামিটার হিসাবে শর্ট ক্লোজার ব্যবহার করতে পারেন। উদাহরণস্বরূপ PHP-এর [array_reduce](https://www.php.net/manual/en/function.array-reduce.php) এর "কলেবল" প্যারামিটার: 1320 | 1321 | ```php 1322 | $myArray = [10,20,30]; 1323 | 1324 | $total = array_reduce($myArray, fn ($carry, $item) => $carry + $item, 0); 1325 | // $total = 60 1326 | ``` 1327 | 1328 | স্বাভাবিক ফাংশন এ টাইপ হিন্টিং অনুমোদিত : 1329 | 1330 | ```php 1331 | fn (int $foo): int => $foo; 1332 | ``` 1333 | 1334 | আপনাকে `return` কীওয়ার্ড ব্যবহার করতে হবে না কারণ এটি এখানে অনুমোদিত নয় : 1335 | 1336 | ```php 1337 | fn ($foo) => return $foo; 1338 | // PHP Parse error: Syntax error, unexpected T_RETURN 1339 | ``` 1340 | 1341 | #### আউটার স্কোপ 1342 | 1343 | শর্ট ক্লোজারের জন্য আউটার স্কোপ থেকে প্রোপার্টিস অ্যাক্সেস করার জন্য `use` কীওয়ার্ডের প্রয়োজন হয় না : 1344 | 1345 | ```php 1346 | $bar = 10; 1347 | $baz = fn ($foo) => $foo + $bar; 1348 | $a = $baz(1); 1349 | //$a = 11 1350 | ``` 1351 | 1352 | কীওয়ার্ড `use` অনুমোদিত নয় : 1353 | 1354 | ```php 1355 | $bar = 10; 1356 | fn ($foo) use ($bar) => $foo + $bar; 1357 | // PHP Parse error: Syntax error, unexpected T_USE, expecting T_DOUBLE_ARROW 1358 | ``` 1359 | 1360 | আপনি অন্য যেকোনো ফাংশনের মতো `$this` ব্যবহার করতে পারেন : 1361 | 1362 | ```php 1363 | fn () => $this->foo + 1; 1364 | ``` 1365 | 1366 | ### ম্যাচ এক্সপ্রেশন 1367 | 1368 | ![php-version-80](https://shields.io/badge/php->=8.0-blue) 1369 | 1370 | PHP 8.0 থেকে, একটি নতুন `match` সিনট্যাক্স আছে `switch` সিনট্যাক্সের মতো। যেহেতু প্রতিটি ম্যাচিং এর ক্ষেত্রে শুধুমাত্র একটি এক্সপ্রেশন থাকতে হবে, তাই এটি ব্যবহার করা যাবে না এবং সেই পরিস্থিতিতে সুইচ স্টেটমেন্ট দিয়ে প্রতিস্থাপন করতে হবে। যদিও এটি উল্লেখযোগ্যভাবে ছোট এবং পড়া সহজ. 1371 | 1372 | ম্যাচ এক্সপ্রেশন সবসময় একটি ভ্যালু রিটার্ণ করে। প্রতিটি শর্ত শুধুমাত্র একটি এক্সপ্রেশনের অনুমতি দেয় এবং এটি অবিলম্বে ভ্যালু রিটার্ণ করে এবং একটি সুস্পষ্ট 'break' বিবৃতি ছাড়া বাকি শর্তগুলিতে যাবেনা : 1373 | 1374 | ```php 1375 | $foo = 'baz'; 1376 | $a = match($foo) { 1377 | 'bar' => 1, 1378 | 'baz' => 2, 1379 | 'qux' => 3, 1380 | } 1381 | // $a = 2 1382 | ``` 1383 | 1384 | ভ্যালু ম্যাচ না করলে এটি এক্সেপশন থ্রো করে: 1385 | 1386 | ```php 1387 | $foo = 'qux'; 1388 | $a = match($foo) { 1389 | 'bar' => 1, 1390 | 'baz' => 2, 1391 | } 1392 | // PHP Error: Unhandled match value of type string 1393 | ``` 1394 | 1395 | কিন্তু এটি একটি ডিফল্ট কন্ডিশন সমর্থন করে: 1396 | 1397 | ```php 1398 | $foo = 'qux'; 1399 | $a = match($foo) { 1400 | 'bar' => 1, 1401 | 'baz' => 2, 1402 | default => 3, 1403 | } 1404 | // $a = 3 1405 | ``` 1406 | 1407 | এটি একটি আর্মে একাধিক শর্তের অনুমতি দেয়: 1408 | 1409 | ```php 1410 | $foo = 'bar'; 1411 | $a = match($foo) { 1412 | 'bar', 'baz' => 1, 1413 | default => 2, 1414 | } 1415 | // $a = 1 1416 | ``` 1417 | 1418 | এটি টাইপ কোয়ার্শন ছাড়াই স্ট্রিক্ট টাইপ-নিরাপদ তুলনা করতে পারে (এটি `==` এর পরিবর্তে `===` ব্যবহার করার মতো): 1419 | 1420 | ```php 1421 | function showType($param) { 1422 | return match ($param) { 1423 | 1 => 'Integer', 1424 | '1' => 'String', 1425 | true => 'Boolean', 1426 | }; 1427 | } 1428 | 1429 | showType(1); // "Integer" 1430 | showType('1'); // "String" 1431 | showType(true); // "Boolean" 1432 | ``` 1433 | 1434 | #### এক্সটারনাল রিসোর্স 1435 | 1436 | - [Match expression on PHP.Watch](https://php.watch/versions/8.0/match-expression) 1437 | 1438 | ### স্ট্রিংয়েবল ইন্টারফেস 1439 | 1440 | ![php-version-80](https://shields.io/badge/php->=8.0-blue) 1441 | 1442 | PHP 8.0 থেকে, একটি নতুন ইন্টারফেস রয়েছে যার নাম `Stringable`, যা নির্দেশ করে একটি ক্লাসের একটি `__toString()` ম্যাজিক মেথডকে। পিএইচপি স্বয়ংক্রিয়ভাবে সমস্ত ক্লাসে স্ট্রিংয়েবল ইন্টারফেস যুক্ত করে দেয় যারা এই মেথডকে ইমপ্লিমেন্ট করেছে . 1443 | 1444 | ```php 1445 | interface Stringable { 1446 | public function __toString(): string; 1447 | } 1448 | ``` 1449 | 1450 | আপনি যখন `Stringable` টাইপের একটি প্যারামিটার ডিফাইন করেন, তখন এটি চেক করবে যে প্রদত্ত ক্লাসটি `Stringable` ইন্টারফেস ইমপ্লিমেন্ট করেছে কিনা: 1451 | 1452 | ```php 1453 | class Foo { 1454 | public function __toString(): string { 1455 | return 'bar'; 1456 | } 1457 | } 1458 | 1459 | function myFunction(Stringable $param): string { 1460 | return (string) $param; 1461 | } 1462 | $a = myFunction(new Foo); 1463 | // $a = 'bar' 1464 | ``` 1465 | 1466 | যদি প্রদত্ত ক্লাস `__toString()` ইমপ্লিমেন্ট না করে, তাহলে আপনি একটি এরর পাবেন : 1467 | 1468 | ```php 1469 | class Foo { 1470 | } 1471 | 1472 | function myFunction(Stringable $param): string { 1473 | return (string) $param; 1474 | } 1475 | $a = myFunction(new Foo); 1476 | // TypeError: myFunction(): Argument #1 ($param) must be of type Stringable, Foo given 1477 | ``` 1478 | 1479 | স্ট্রিংয়েবল টাইপ স্ট্রিং গ্রহণ করে না: 1480 | 1481 | ```php 1482 | function myFunction(Stringable $param): string { 1483 | return (string) $param; 1484 | } 1485 | $a = myFunction('foo'); 1486 | // TypeError: myFunction(): Argument #1 ($param) must be of type Stringable, string given 1487 | ``` 1488 | 1489 | অবশ্যই, স্ট্রিং এবং স্ট্রিংএবল উভয়ই গ্রহণ করার জন্য, আপনি ইউনিয়ন টাইপ ব্যবহার করতে পারেন: 1490 | 1491 | ```php 1492 | function myFunction(string|Stringable $param): string { 1493 | return (string) $param; 1494 | } 1495 | ``` 1496 | 1497 | -------------------------------------------------------------------------------- /translations/es-AR.md: -------------------------------------------------------------------------------- 1 | # PHP Moderno Cheatsheet 2 | 3 | ![PHP Moderno Cheatsheet](https://i.imgur.com/2STEtgG.png) 4 | 5 | 6 | > Si te gusta este contenido, podés contactarme o seguirme en Twitter. :+1: 7 | 8 | [![Tweet for help](https://img.shields.io/twitter/follow/smknstd?label=Tweet%20%40smknstd&style=social)](https://twitter.com/smknstd/) 9 | 10 | Traducción por: [Cristian Ferreyra](https://github.com/backendrulz) [![backendrulz](https://img.shields.io/twitter/follow/backendrulz?label=Tweet%20%40backendrulz&style=social)](https://twitter.com/backendrulz/) 11 | > **Nota de traducción:** Elegí no traducir algunos términos ya que son extremadamente técnicos y podrían dificultar el aprendizaje de futuros lectores. 12 | 13 | ## Introducción 14 | 15 | ### Motivación 16 | 17 | Este documento es un cheatsheet para PHP con código que encontrará con frecuencia en proyectos modernos. 18 | 19 | Esta guía no está destinada a enseñarte PHP desde cero, sino a ayudar a los desarrolladores con conocimientos básicos que pueden tener dificultades para familiarizarse con las bases de código modernas (o para aprender Laravel o Symfony, por ejemplo) debido a los nuevos conceptos y características que PHP ha introducido a lo largo de los años. 20 | 21 | > **Nota:** Los conceptos presentados acá se basan en la versión más reciente de PHP disponible ([PHP 8.1](https://www.php.net/releases/8.1/es.php) en el momento de la última actualización) 22 | 23 | ### Recursos complementarios 24 | 25 | Cuando tengas dificultad para comprender un concepto, te sugiero que busques respuestas en los siguientes sitios: 26 | - [Stitcher's blog](https://stitcher.io/blog) 27 | - [PHP.Watch](https://php.watch/versions) 28 | - [Exploring PHP 8.0](https://leanpub.com/exploringphp80) 29 | - [PHP 8 in a nutshell](https://amitmerchant.gumroad.com/l/php8-in-a-nutshell) 30 | - [PHP The Right Way](https://phptherightway.com/) 31 | - [StackOverflow](https://stackoverflow.com/questions/tagged/php) 32 | 33 | ### Lanzamientos recientes de PHP 34 | 35 | | Version |Fecha de lanzamiento| 36 | |----------------------------------------------|---| 37 | | [PHP 8.2](https://www.php.net/releases/8.2/en.php) |Diciembre 2022| 38 | | [PHP 8.1](https://www.php.net/releases/8.1/es.php) |Noviembre 2021| 39 | | [PHP 8.0](https://www.php.net/releases/8.0/es.php) |Noviembre 2020| 40 | | PHP 7.4 |Noviembre 2019| 41 | | PHP 7.3 |Diciembre 2018| 42 | | PHP 7.2 |Noviembre 2017| 43 | | PHP 7.1 |Diciembre 2016| 44 | | PHP 7.0 |Diciembre 2015| 45 | 46 | Mas información en [php.net](https://www.php.net/supported-versions.php). 47 | 48 | ## Tabla de contenidos 49 | 50 | - [PHP moderno cheatsheet](#php-moderno-cheatsheet) 51 | * [Introducción](#introducción) 52 | + [Motivación](#motivación) 53 | + [Recursos complementarios](#recursos-complementarios) 54 | + [Lanzamientos recientes de PHP](#lanzamientos-recientes-de-php) 55 | * [Tabla de contenidos](#tabla-de-contenidos) 56 | * [Fundamentos](#fundamentos) 57 | + [Parámetro por defecto de función](#parámetro-por-defecto-de-función) 58 | + [Coma final](#coma-final) 59 | + [Declaración de tipo](#declaración-de-tipo) 60 | + [Desestructuración de matrices](#desestructuración-de-matrices) 61 | + [Null Coalescing](#null-coalescing) 62 | + [Operador Nullsafe](#operador-nullsafe) 63 | + [Operador Spread](#operador-spread) 64 | + [Argumentos nombrados](#argumentos-nombrados) 65 | + [Funciones flecha](#funciones-flecha) 66 | + [Expresión de coincidencia Match](#expresión-de-coincidencia-match) 67 | + [Interfaz Stringable](#interfaz-stringable) 68 | + [Enums](#enums) 69 | 70 | ## Fundamentos 71 | 72 | ### Parámetro por defecto de función 73 | 74 | Podés establecer un valor predeterminado para tus parámetros de función: 75 | 76 | ```php 77 | function myFunction($param = 'foo') 78 | { 79 | return $param; 80 | } 81 | $a = myFunction(); 82 | // $a = 'foo' 83 | 84 | $b = myFunction('bar'); 85 | // $b = 'bar' 86 | ``` 87 | 88 | Pero si enviás una propiedad nula o indefinida, no se utilizará el valor predeterminado: 89 | 90 | ```php 91 | function myFunction($param = 'foo') 92 | { 93 | return $param; 94 | } 95 | $a = myFunction(null); 96 | // $a = null 97 | 98 | $b = myFunction($undefined); // PHP Warning: Undefined variable $undefined 99 | // $b = null 100 | ``` 101 | 102 | ### Coma final 103 | 104 | Una coma final es un símbolo de coma que se escribe después del último elemento de una lista de elementos. Uno de los principales beneficios cuando se usa con multilíneas es que [las diferencias son más limpias](https://medium.com/@nikgraf/why-you-should-enforce-dangling-commas-for-multiline-statements-d034c98e36f8). 105 | 106 | #### Matriz 107 | 108 | Podés usar una coma final en matrices: 109 | 110 | ```php 111 | $array = [ 112 | 'foo', 113 | 'bar', 114 | ]; 115 | ``` 116 | 117 | #### Declaración de uso agrupado 118 | 119 | ![php-version-72](https://shields.io/badge/php->=7.2-blue) 120 | 121 | Desde PHP 7.2, podés usar una coma final en declaraciones de uso agrupadas: 122 | 123 | ```php 124 | use Symfony\Component\HttpKernel\{ 125 | Controller\ControllerResolverInterface, 126 | Exception\NotFoundHttpException, 127 | Event\PostResponseEvent, 128 | }; 129 | ``` 130 | 131 | #### Llamada de función y método 132 | 133 | ![php-version-73](https://shields.io/badge/php->=7.3-blue) 134 | 135 | Desde PHP 7.3, podés usar una coma final al llamar a una función: 136 | 137 | ```php 138 | function myFunction($foo, $bar) 139 | { 140 | return true; 141 | } 142 | $a = myFunction( 143 | 'baz', 144 | 'qux', 145 | ); 146 | ``` 147 | 148 | y al llamar a un método: 149 | 150 | ```php 151 | $f = new Foo(); 152 | $f->myMethod( 153 | 'baz', 154 | 'qux', 155 | ); 156 | ``` 157 | 158 | #### Parámetros de función 159 | 160 | ![php-version-80](https://shields.io/badge/php->=8.0-blue) 161 | 162 | Desde PHP 8.0, podés usar una coma final al declarar los parámetros de una función: 163 | 164 | ```php 165 | function myFunction( 166 | $foo, 167 | $bar, 168 | ) 169 | { 170 | return true; 171 | } 172 | ``` 173 | 174 | #### Declaración de uso 175 | 176 | ![php-version-80](https://shields.io/badge/php->=8.0-blue) 177 | 178 | Desde PHP 8.0, podés usar una coma final en la declaración de uso: 179 | 180 | ```php 181 | function() use ( 182 | $foo, 183 | $bar, 184 | ) 185 | { 186 | return true; 187 | } 188 | ``` 189 | 190 | ### Declaración de tipo 191 | 192 | ![php-version-70](https://shields.io/badge/php->=7.0-blue) 193 | 194 | Con la declaración de tipo, se puede especificar el tipo de datos esperado para una propiedad que se aplicará en tiempo de ejecución. Admite muchos tipos, como tipos escalares (int, string, bool y float), pero también array, iterable, object, stdClass, etc. 195 | 196 | Podés establecer un tipo para el parámetro de una función: 197 | 198 | ```php 199 | function myFunction(int $param) 200 | { 201 | return $param; 202 | } 203 | $a = myFunction(10); 204 | // $a = 10 205 | $b = myFunction('foo'); // TypeError: myFunction(): Argument #1 ($param) must be of type int, string given 206 | ``` 207 | 208 | También se puede establecer un tipo de retorno para una función: 209 | 210 | ```php 211 | function myFunction() : int 212 | { 213 | return 'foo'; 214 | } 215 | $a = myFunction(); // TypeError: myFunction(): Return value must be of type int, string returned 216 | ``` 217 | 218 | Cuando una función no debería devolver algo, se puede usar el tipo "void": 219 | 220 | ```php 221 | function myFunction() : void 222 | { 223 | return 'foo'; 224 | } 225 | // PHP Fatal error: A void function must not return a value 226 | ``` 227 | 228 | Tampoco puede devolver null: 229 | 230 | ```php 231 | function myFunction() : void 232 | { 233 | return null; 234 | } 235 | // PHP Fatal error: A void function must not return a value 236 | ``` 237 | 238 | Sin embargo, usar return para salir de la función es válido: 239 | 240 | ```php 241 | function myFunction() : void 242 | { 243 | return; 244 | } 245 | $a = myFunction(); 246 | // $a = null 247 | ``` 248 | 249 | #### Propiedad de clase 250 | 251 | ![php-version-74](https://shields.io/badge/php->=7.4-blue) 252 | 253 | Podés establecer un tipo en una propiedad de clase: 254 | 255 | ```php 256 | Class Foo() 257 | { 258 | public int $bar; 259 | } 260 | $f = new Foo(); 261 | $f->bar = 'baz'; // TypeError: Cannot assign string to property Foo::$bar of type int 262 | ``` 263 | 264 | #### Tipo de unión 265 | 266 | ![php-version-80](https://shields.io/badge/php->=8.0-blue) 267 | 268 | Podés utilizar un "tipo de unión" que acepte valores de varios tipos diferentes, en lugar de uno solo: 269 | 270 | ```php 271 | function myFunction(string|int|array $param) : string|int|array 272 | { 273 | return $param; 274 | } 275 | ``` 276 | 277 | También funciona con las propiedades de la clase: 278 | 279 | ```php 280 | Class Foo() 281 | { 282 | public string|int|array $bar; 283 | } 284 | ``` 285 | 286 | #### Tipo de intersección 287 | 288 | ![php-version-81](https://shields.io/badge/php->=8.1-blue) 289 | 290 | Desde PHP 8.1, podés usar un "tipo de intersección" (también conocido como "puro") que exige que un valor dado pertenezca a todos los tipos. Por ejemplo, este parámetro necesita implementar las interfaces *Stringable* y *Countable*: 291 | 292 | ```php 293 | function myFunction(Stringable&Countable $param): Stringable&Countable 294 | { 295 | return $param; 296 | } 297 | Class Foo 298 | { 299 | public function __toString() { 300 | return "something"; 301 | } 302 | } 303 | myFunction(new Foo()); 304 | // TypeError: myFunction(): Argument #1 ($param) must be of type Stringable&Countable, Foo given 305 | ``` 306 | 307 | También funciona con propiedades de clase: 308 | 309 | ```php 310 | Class Foo 311 | { 312 | public Stringable&Countable $bar; 313 | } 314 | ``` 315 | 316 | El tipo de intersección solo admite clases e interfaces. Los tipos escalares (string, int, array, null, mixed, etc.) no están permitidos: 317 | 318 | ```php 319 | function myFunction(string&Countable $param) 320 | { 321 | return $param; 322 | } 323 | // PHP Fatal error: Type string cannot be part of an intersection type 324 | ``` 325 | 326 | ##### Recurso externo 327 | 328 | - [Intersection types on PHP.Watch](https://php.watch/versions/8.1/intersection-types) 329 | 330 | #### Tipo Nullable 331 | 332 | ![php-version-71](https://shields.io/badge/php->=7.1-blue) 333 | 334 | Cuando un parámetro no tiene tipo, puede aceptar un valor nulo: 335 | 336 | ```php 337 | function myFunction($param) 338 | { 339 | return $param; 340 | } 341 | $a = myFunction(null); 342 | // $a = null 343 | ``` 344 | 345 | Pero tan pronto como un parámetro tenga un tipo, ya no aceptará un valor nulo y devolverá un error: 346 | 347 | ```php 348 | function myFunction(string $param) 349 | { 350 | return $param; 351 | } 352 | $a = myFunction(null); // TypeError: myFunction(): Argument #1 ($param) must be of type string, null given 353 | ``` 354 | 355 | Si una función tiene un tipo de retorno, tampoco aceptará un valor nulo: 356 | 357 | ```php 358 | function myFunction() : string 359 | { 360 | return null; 361 | } 362 | $a = myFunction(); // TypeError: myFunction(): Return value must be of type string, null returned 363 | ``` 364 | 365 | Podés hacer una declaración de tipo explícitamente "nullable": 366 | 367 | ```php 368 | function myFunction(?string $param) 369 | { 370 | return $param; 371 | } 372 | $a = myFunction(null); 373 | // $a = null 374 | ``` 375 | 376 | o con un tipo de unión: 377 | 378 | ```php 379 | function myFunction(string|null $param) 380 | { 381 | return $param; 382 | } 383 | $a = myFunction(null); 384 | // $a = null 385 | ``` 386 | 387 | También funciona con el tipo de retorno: 388 | 389 | ```php 390 | function myFunction(?string $param) : ?string 391 | { 392 | return $param; 393 | } 394 | // or 395 | function myFunction(string|null $param) : string|null 396 | { 397 | return $param; 398 | } 399 | ``` 400 | 401 | Pero void no puede ser "nullable": 402 | 403 | ```php 404 | function myFunction() : ?void 405 | { 406 | // algún código 407 | } 408 | // PHP Fatal error: Void type cannot be nullable 409 | ``` 410 | 411 | o 412 | 413 | ```php 414 | function myFunction() : void|null 415 | { 416 | // algún código 417 | } 418 | // PHP Fatal error: Void type cannot be nullable 419 | ``` 420 | 421 | Podés establecer un tipo que acepta valores null en una propiedad de clase: 422 | 423 | ```php 424 | Class Foo() 425 | { 426 | public int|null $bar; 427 | } 428 | $f = new Foo(); 429 | $f->bar = null; 430 | $a = $f->bar; 431 | // $a = null 432 | ``` 433 | 434 | ### Desestructuración de matrices 435 | 436 | Podés desestructurar matrices para extraer varios elementos en variables independientes. 437 | 438 | #### Matriz indexada 439 | 440 | ![php-version-40](https://shields.io/badge/php->=4.0-blue) 441 | 442 | Considerando una matriz indexada como: 443 | 444 | ```php 445 | $array = ['foo', 'bar', 'baz']; 446 | ``` 447 | 448 | Podés desestructurar la matriz usando la sintaxis de lista: 449 | 450 | ```php 451 | list($a, $b, $c) = $array; 452 | 453 | // $a = 'foo' 454 | // $b = 'bar' 455 | // $c = 'baz' 456 | ``` 457 | 458 | O a partir de PHP 7.1, usando la sintaxis corta: 459 | 460 | ```php 461 | [$a, $b, $c] = $array; 462 | 463 | // $a = 'foo' 464 | // $b = 'bar' 465 | // $c = 'baz' 466 | ``` 467 | 468 | Podés saltar elementos: 469 | 470 | ```php 471 | list(, , $c) = $array; 472 | 473 | // $c = 'baz' 474 | ``` 475 | 476 | O a partir de PHP 7.1, usando la sintaxis corta: 477 | 478 | ```php 479 | [, , $c] = $array; 480 | 481 | // $c = 'baz' 482 | ``` 483 | 484 | Cuando intentes desestructurar un índice que no existe, obtendrás una advertencia: 485 | 486 | ```php 487 | list($a, $b, $c, $d) = $array; // PHP Warning: Undefined array key 3 488 | 489 | // $a = 'foo' 490 | // $b = 'bar' 491 | // $c = 'baz' 492 | // $d = null; 493 | ``` 494 | 495 | También podés intercambiar variables con asignaciones de desestructuración, considerando que tenés variables como: 496 | ```php 497 | $a = 'foo'; 498 | $b = 'bar'; 499 | ``` 500 | 501 | Entonces, si necesitás intercambiar `$a` y `$b` en lugar de usar una variable temporal como esta: 502 | 503 | ```php 504 | $temp = $a; 505 | $a = $b; 506 | $b = $temp; 507 | 508 | // $a = 'bar' 509 | // $b = 'foo' 510 | ``` 511 | 512 | Podés intercambiarlas usando la sintaxis de lista: 513 | 514 | ```php 515 | list($a, $b) = [$b, $a]; 516 | 517 | // $a = 'bar' 518 | // $b = 'foo' 519 | ``` 520 | 521 | O desde PHP 7.1, la sintaxis abreviada: 522 | 523 | ```php 524 | [$a, $b] = [$b, $a]; 525 | 526 | // $a = 'bar' 527 | // $b = 'foo' 528 | ``` 529 | 530 | #### Matriz asociativa 531 | 532 | ![php-version-71](https://shields.io/badge/php->=7.1-blue) 533 | 534 | Considerando una matriz asociativa (con clave de cadena) como: 535 | 536 | ```php 537 | $array = [ 538 | 'foo' => 'value1', 539 | 'bar' => 'value2', 540 | 'baz' => 'value3', 541 | ]; 542 | ``` 543 | 544 | La sintaxis de la lista anterior no funcionará con una matriz asociativa y recibirá una advertencia: 545 | 546 | ```php 547 | list($a, $b, $c) = $array; // PHP Warning: Undefined array key 0 ... 548 | 549 | // $a = null 550 | // $b = null 551 | // $c = null 552 | ``` 553 | 554 | Pero desde PHP 7.1 (~ diciembre 2016), podés desestructurar la matriz con otra sintaxis basada en llaves: 555 | 556 | ```php 557 | list('foo' => $a, 'bar' => $b, 'baz' => $c) = $array; 558 | 559 | // $a = 'value1' 560 | // $b = 'value2' 561 | // $c = 'value3' 562 | ``` 563 | 564 | O usando la sintaxis corta: 565 | 566 | ```php 567 | ['foo' => $a, 'bar' => $b, 'baz' => $c] = $array; 568 | 569 | // $a = 'value1' 570 | // $b = 'value2' 571 | // $c = 'value3' 572 | ``` 573 | 574 | También podés desestructurar solamente una parte de la matriz (el órden no importa): 575 | 576 | ```php 577 | ['baz' => $c, 'foo' => $a] = $array; 578 | 579 | // $a = 'value1' 580 | // $c = 'value3' 581 | ``` 582 | 583 | Cuando trates de desestructurar una llave que no exista en la matriz, recibirás una advertencia: 584 | 585 | ```php 586 | list('moe' => $d) = $array; // PHP Warning: Undefined array key "moe" 587 | 588 | // $d = null 589 | ``` 590 | 591 | ### Null Coalescing 592 | 593 | ![php-version-70](https://shields.io/badge/php->=7.0-blue) 594 | 595 | Desde PHP 7.0 (~ diciembre 2015), podés usar el operador null coalescing para proporcionar un respaldo cuando una propiedad es nula sin error ni advertencia: 596 | 597 | ```php 598 | $a = null; 599 | $b = $a ?? 'fallback'; 600 | 601 | // $b = 'fallback' 602 | ``` 603 | 604 | Es equivalente a: 605 | 606 | ```php 607 | $a = null; 608 | $b = isset($a) ? $a : 'fallback'; 609 | // $b = 'fallback' 610 | ``` 611 | 612 | También funciona cuando la propiedad es indefinida: 613 | 614 | ```php 615 | $a = $undefined ?? 'fallback'; 616 | 617 | // $a = 'fallback' 618 | ``` 619 | 620 | Cualquier otro valor de la propiedad no activará el respaldo (fallback): 621 | 622 | ```php 623 | '' ?? 'fallback'; // '' 624 | 0 ?? 'fallback'; // 0 625 | false ?? 'fallback'; // false 626 | ``` 627 | 628 | Se puede encadenar el null coalescing varias veces: 629 | 630 | ```php 631 | $a = null; 632 | $b = null; 633 | $c = $a ?? $b ?? 'fallback'; 634 | // $c = 'fallback' 635 | ``` 636 | 637 | #### Operador Elvis 638 | 639 | ![php-version-53](https://shields.io/badge/php->=5.3-blue) 640 | 641 | No se debe confundir con el operador ternario corto (también conocido como el operador elvis), que se introdujo en PHP 5.3: 642 | 643 | ```php 644 | $a = null; 645 | $b = $a ?: 'fallback'; 646 | 647 | // $b = 'fallback' 648 | ``` 649 | 650 | El operador ternario corto es equivalente a: 651 | 652 | ```php 653 | $a = null; 654 | $b = $a ? $a : 'fallback'; 655 | // $b = 'fallback' 656 | ``` 657 | 658 | El resultado entre null coalescing y el operador Elvis puede ser similar, pero también diferente para algunos valores específicos: 659 | 660 | ```php 661 | '' ?: 'fallback'; // 'fallback' 662 | 0 ?: 'fallback'; // 'fallback' 663 | false ?: 'fallback'; // 'fallback' 664 | ``` 665 | 666 | #### Null coalescing en matriz 667 | 668 | Si existe una clave de matriz, no se activa el respaldo: 669 | 670 | ```php 671 | $a = ['foo' => 'bar']; 672 | $b = $a['foo'] ?? 'fallback'; 673 | 674 | // $b = 'bar' 675 | ``` 676 | 677 | Pero cuando la matriz no existe, se activa el respaldo sin error ni advertencia: 678 | 679 | ```php 680 | $a = null; 681 | $b = $a['foo'] ?? 'fallback'; 682 | 683 | // $b = 'fallback' 684 | ``` 685 | 686 | O si la propiedad de la matriz no está definida, el respaldo se activa sin errores ni advertencias: 687 | 688 | ```php 689 | $b = $undefined['foo'] ?? 'fallback'; 690 | 691 | // $b = 'fallback' 692 | ``` 693 | 694 | Cuando existe una matriz pero no se puede encontrar la clave, se activa el respaldo sin error ni advertencia: 695 | 696 | ```php 697 | $a = []; 698 | $b = $a['foo'] ?? 'fallback'; 699 | 700 | // $b = 'fallback' 701 | ``` 702 | 703 | También funciona con matrices indexadas: 704 | 705 | ```php 706 | $a = ['foo']; 707 | 708 | // reminder: $a[0] = 'foo' 709 | 710 | $b = $a[1] ?? 'fallback'; 711 | 712 | // $b = 'fallback' 713 | ``` 714 | 715 | También funciona con matrices anidadas. Si existe una clave de matriz anidada, no se activa el respaldo: 716 | 717 | ```php 718 | $a = [ 719 | 'foo' => [ 720 | 'bar' => 'baz' 721 | ] 722 | ]; 723 | $b = $a['foo']['bar'] ?? 'fallback'; 724 | 725 | // $b = 'baz' 726 | ``` 727 | 728 | Pero cuando no se puede encontrar la clave anidada, se activa el respaldo sin error ni advertencia: 729 | 730 | ```php 731 | $a = [ 732 | 'foo' => [ 733 | 'bar' => 'baz' 734 | ] 735 | ]; 736 | $b = $a['foo']['qux'] ?? 'fallback'; 737 | 738 | // $b = 'fallback' 739 | ``` 740 | 741 | #### Null coalescing en objeto 742 | 743 | También podés usar el operador null coalescing con objectos. 744 | 745 | ##### Atributo del objeto 746 | 747 | Si existe el atributo del objeto, no se activa el respaldo: 748 | 749 | ```php 750 | $a = (object)[ 751 | 'foo' => 'bar' 752 | ]; 753 | $b = $a->foo ?? 'fallback'; 754 | 755 | // $b = 'bar' 756 | ``` 757 | 758 | Pero cuando no se puede encontrar el atributo del objeto, se activa el respaldo sin error ni advertencia: 759 | 760 | ```php 761 | $a = (object)[ 762 | 'foo' => 'bar' 763 | ]; 764 | $b = $a->baz ?? 'fallback'; 765 | 766 | // $b = 'fallback' 767 | ``` 768 | 769 | ##### Método de objeto 770 | 771 | También podés utilizar el operador null coalescing en la llamada al método de un objeto. Si el método existe, entonces no se activa el respaldo: 772 | 773 | ```php 774 | class Foo 775 | { 776 | public function bar() 777 | { 778 | return 'baz'; 779 | } 780 | } 781 | 782 | $a = new Foo(); 783 | $b = $a->bar() ?? 'fallback'; 784 | 785 | // $b = 'baz' 786 | ``` 787 | 788 | Pero cuando el método del objeto devuelve nulo, se activa el respaldo sin error ni advertencia: 789 | 790 | ```php 791 | class Foo 792 | { 793 | public function bar() 794 | { 795 | return null; 796 | } 797 | } 798 | 799 | $a = new Foo(); 800 | $b = $a->bar() ?? 'fallback'; 801 | 802 | // $b = 'fallback' 803 | ``` 804 | 805 | Si no se puede encontrar el método del objeto, null coalescing no funcionará y obtendrás un error: 806 | 807 | ```php 808 | class Foo 809 | { 810 | public function bar() 811 | { 812 | return 'baz'; 813 | } 814 | } 815 | 816 | $a = new Foo(); 817 | $b = $a->baz() ?? 'fallback'; // PHP Error: Call to undefined method baz() 818 | ``` 819 | 820 | ##### Método encadenado 821 | 822 | Cuando se utilizan métodos encadenados en un objeto y no se puede encontrar un elemento intermediario, null coalescing no funcionará y obtendrás un error: 823 | 824 | ```php 825 | class Foo 826 | { 827 | public function bar() 828 | { 829 | return (object)[]; 830 | } 831 | } 832 | 833 | $a = new Foo(); 834 | $b = $a->bar()->baz() ?? 'fallback'; // PHP Error: Call to undefined method baz() 835 | ``` 836 | 837 | #### Operador de asignación de Null Coalescing 838 | 839 | ![php-version-74](https://shields.io/badge/php->=7.4-blue) 840 | 841 | Podés establecer un valor predeterminado para una propiedad cuando es nulo: 842 | 843 | ```php 844 | $a = null; 845 | $a = $a ?? 'foo'; 846 | // $a = 'foo' 847 | ``` 848 | 849 | Desde PHP 7.4, podés usar el operador de asignación de null coalescing para hacer lo mismo: 850 | 851 | ```php 852 | $a = null; 853 | $a ??= 'foo'; 854 | // $a = 'foo' 855 | ``` 856 | 857 | ### Operador Nullsafe 858 | 859 | ![php-version-80](https://shields.io/badge/php->=8.0-blue) 860 | 861 | Cuando intentes leer una propiedad o llames a un método en nulo, devolverá una advertencia y un error: 862 | 863 | ```php 864 | $a = null; 865 | $b = $a->foo; // PHP Warning: Attempt to read property "foo" on null 866 | // $b = null 867 | 868 | $c = $a->foo(); // PHP Error: Call to a member function foo() on null 869 | ``` 870 | 871 | Con el operador nullsafe, se pueden hacer ambas cosas sin advertencia ni error: 872 | 873 | ```php 874 | $a = null; 875 | $b = $a?->foo; 876 | // $b = null 877 | $c = $a?->foo(); 878 | // $c = null 879 | ``` 880 | 881 | Se pueden encadenar varios operadores nullsafe: 882 | 883 | ```php 884 | $a = null; 885 | $b = $a?->foo?->bar; 886 | // $b = null 887 | $c = $a?->foo()?->bar(); 888 | // $c = null 889 | ``` 890 | 891 | Una expresión está en cortocircuito desde el primer operador null-safe que encuentra un valor nulo: 892 | 893 | ```php 894 | $a = null; 895 | $b = $a?->foo->bar->baz(); 896 | // $b = null 897 | ``` 898 | 899 | El operador nullsafe no tiene ningún efecto si el objetivo no es nulo: 900 | 901 | ```php 902 | $a = 'foo'; 903 | $b = $a?->bar; // PHP Warning: Attempt to read property "bar" on string 904 | // $b = null 905 | $c = $a?->baz(); // PHP Error: Call to a member function baz() on string 906 | ``` 907 | 908 | El operador Nullsafe no puede manejar las matrices correctamente, pero aún puede tener algún efecto: 909 | 910 | ```php 911 | $a = []; 912 | $b = $a['foo']->bar; 913 | // PHP Warning: Undefined array key "foo" 914 | // PHP Warning: Attempt to read property "bar" on null 915 | // $b = null 916 | 917 | $c = $a['foo']?->bar; // PHP Warning: Undefined array key "foo" 918 | // $c = null 919 | 920 | $d = $a['foo']->bar(); 921 | // PHP Warning: Undefined array key "foo" 922 | // PHP Error: Call to a member function bar() on null 923 | 924 | $e = $a['foo']?->bar(); // PHP Warning: Undefined array key "foo" 925 | // $e = null 926 | ``` 927 | 928 | No se puede usar el operador nullsafe para escribir, es de solo lectura: 929 | 930 | ```php 931 | $a = null; 932 | $a?->foo = 'bar'; // PHP Fatal error: Can't use nullsafe operator in write context 933 | ``` 934 | 935 | ### Operador Spread 936 | 937 | #### Parámetro Variadic 938 | 939 | ![php-version-56](https://shields.io/badge/php->=5.6-blue) 940 | 941 | Desde PHP 5.6 (~ agosto 2014), se puede agregar un parámetro variadic a cualquier función que te permita usar listas de argumentos con longitud variable: 942 | 943 | ```php 944 | function countParameters(string $param, string ...$options) : int 945 | { 946 | 947 | foreach ($options as $option) { 948 | // podés iterar en $options 949 | } 950 | 951 | return 1 + count($options); 952 | } 953 | 954 | countParameters('foo'); // 1 955 | countParameters('foo', 'bar'); // 2 956 | countParameters('foo', 'bar', 'baz'); // 3 957 | ``` 958 | 959 | El parámetro variadic siempre debe ser el último parámetro declarado: 960 | 961 | ```php 962 | function countParameters(string ...$options, string $param) 963 | { 964 | // algún código 965 | } 966 | // PHP Fatal error: Only the last parameter can be variadic 967 | ``` 968 | 969 | Solo se puede tener un parámetro variadic: 970 | 971 | ```php 972 | function countParameters(string ...$options, string ...$moreOptions) 973 | { 974 | // algún código 975 | } 976 | // PHP Fatal error: Only the last parameter can be variadic 977 | ``` 978 | 979 | No puede tener un valor predeterminado: 980 | 981 | ```php 982 | function countParameters(string $param, string ...$options = []) 983 | { 984 | // algún código 985 | } 986 | // PHP Parse error: Variadic parameter cannot have a default value 987 | ``` 988 | 989 | Cuando no es tipado, acepta cualquier valor: 990 | 991 | ```php 992 | function countParameters(string $param, ...$options) : int 993 | { 994 | return 1 + count($options); 995 | } 996 | 997 | $a = countParameters('foo', null, [], true); 998 | // $a = 4 999 | ``` 1000 | 1001 | Cuando es tipado, tenés que usar valores correctamente definidos: 1002 | 1003 | ```php 1004 | function countParameters(string $param, string ...$options) : int 1005 | { 1006 | return 1 + count($options); 1007 | } 1008 | 1009 | countParameters('foo', null); 1010 | // TypeError: countParameters(): Argument #2 must be of type string, null given 1011 | 1012 | countParameters('foo', []); 1013 | // TypeError: countParameters(): Argument #2 must be of type string, array given 1014 | ``` 1015 | 1016 | #### Desempaquetando argumentos 1017 | 1018 | ![php-version-56](https://shields.io/badge/php->=5.6-blue) 1019 | 1020 | Las matrices y los objetos traversable se pueden desempaquetar en listas de argumentos al llamar a funciones mediante el operador spread: 1021 | 1022 | ```php 1023 | function add(int $a, int $b, int $c) : int 1024 | { 1025 | return $a + $b + $c; 1026 | } 1027 | $array = [2, 3]; 1028 | $r = add(1, ...$array); 1029 | 1030 | // $r = 6 1031 | ``` 1032 | 1033 | La matriz puede tener más elementos de los necesarios: 1034 | 1035 | ```php 1036 | function add(int $a, int $b, int $c) : int 1037 | { 1038 | return $a + $b + $c; 1039 | } 1040 | $array = [2, 3, 4, 5]; 1041 | $r = add(1, ...$array); 1042 | 1043 | // $r = 6 1044 | ``` 1045 | 1046 | La matriz no puede tener menos elementos de los necesarios: 1047 | 1048 | ```php 1049 | function add(int $a, int $b, int $c) : int 1050 | { 1051 | return $a + $b + $c; 1052 | } 1053 | $array = [2]; 1054 | $r = add(1, ...$array); // TypeError: Too few arguments to function add(), 2 passed 1055 | ``` 1056 | 1057 | Excepto cuando algunos argumentos tienen un valor predeterminado: 1058 | 1059 | ```php 1060 | function add(int $a, int $b, int $c = 0) : int 1061 | { 1062 | return $a + $b + $c; 1063 | } 1064 | $array = [2]; 1065 | $r = add(1, ...$array); 1066 | // $r = 3 1067 | ``` 1068 | 1069 | Si un argumento es tipado y el valor no coincide con el tipo, obtendrás un error: 1070 | 1071 | ```php 1072 | function add(int $a, int $b, int $c) : int 1073 | { 1074 | return $a + $b + $c; 1075 | } 1076 | $array = ['foo', 'bar']; 1077 | $r = add(1, ...$array); // TypeError: add(): Argument #2 ($b) must be of type int, string given 1078 | ``` 1079 | 1080 | Desde PHP 8.0, es posible desempaquetar una matriz asociativa ya que usará [argumentos nombrados](#unpacking-named-arguments). 1081 | 1082 | #### Desempaquetado de Matriz 1083 | 1084 | ##### Matriz indexada 1085 | 1086 | ![php-version-74](https://shields.io/badge/php->=7.4-blue) 1087 | 1088 | Cuando se desea fusionar varias matrices, generalmente se usa `array_merge`: 1089 | 1090 | ```php 1091 | $array1 = ['baz']; 1092 | $array2 = ['foo', 'bar']; 1093 | 1094 | $array3 = array_merge($array1, $array2); 1095 | // $array3 = ['baz', 'foo', 'bar'] 1096 | ``` 1097 | 1098 | Pero desde PHP 7.4 (~ noviembre 2019), se pueden desempaquetar matrices indexadas con el operador spread: 1099 | 1100 | ```php 1101 | $array1 = ['foo', 'bar']; 1102 | $array2 = ['baz', ...$array1]; 1103 | // $array2 = ['baz', 'foo', 'bar'] 1104 | ``` 1105 | 1106 | Los elementos se fusionarán en el orden en que se pasen: 1107 | 1108 | ```php 1109 | $array1 = ['foo', 'bar']; 1110 | $array2 = ['baz', ...$array1, "qux"]; 1111 | // $array2 = ['baz', 'foo', 'bar', "qux"] 1112 | ``` 1113 | 1114 | No se realiza ninguna deduplicación: 1115 | 1116 | ```php 1117 | $array1 = ['foo', 'bar']; 1118 | $array2 = ['foo', ...$array1]; 1119 | // $array2 = ['foo', 'foo', 'bar'] 1120 | ``` 1121 | 1122 | Se pueden desempaquetar varias matrices a la vez: 1123 | 1124 | ```php 1125 | $array1 = ['foo', 'bar']; 1126 | $array2 = ['baz']; 1127 | $array3 = [ ...$array1, ...$array2]; 1128 | // $array3 = ['foo', 'bar', 'baz'] 1129 | ``` 1130 | 1131 | Se puede desempaquetar la misma matriz varias veces: 1132 | 1133 | ```php 1134 | $array1 = ['foo', 'bar']; 1135 | $array2 = [ ...$array1, ...$array1]; 1136 | // $array2 = ['foo', 'bar', 'foo', 'bar'] 1137 | ``` 1138 | 1139 | Podés desempaquetar una matriz vacía sin errores ni advertencias: 1140 | 1141 | ```php 1142 | $array1 = []; 1143 | $array2 = ['foo', ...$array1]; 1144 | // $array2 = ['foo'] 1145 | ``` 1146 | 1147 | Podés desempaquetar una matriz que no ha sido almacenada previamente en una propiedad: 1148 | 1149 | ```php 1150 | $array1 = [...['foo', 'bar'], 'baz']; 1151 | // $array1 = ['foo', 'bar', 'baz'] 1152 | ``` 1153 | 1154 | El desempaquetado solo funciona con matrices (u objetos que complementan la interfaz Traversable). Si intentás desempaquetar cualquier otro valor (como nulo), generará un error: 1155 | 1156 | ```php 1157 | $array1 = null; 1158 | $array2 = ['foo', ...$array1]; // PHP Error: Only arrays and Traversables can be unpacked 1159 | ``` 1160 | 1161 | Podés desempaquetar el resultado de una función/método: 1162 | 1163 | ```php 1164 | function getArray() : array 1165 | { 1166 | return ['foo', 'bar']; 1167 | } 1168 | 1169 | $array = [...getArray(), 'baz']; 1170 | // $array = ['foo', 'bar', 'baz'] 1171 | ``` 1172 | 1173 | ##### Matriz asociativa 1174 | 1175 | ![php-version-81](https://shields.io/badge/php->=8.1-blue) 1176 | 1177 | Desde php 8.1, podés desempaquetar una matriz asociativa (con clave de cadena): 1178 | 1179 | ```php 1180 | $array1 = ['foo' => 'bar']; 1181 | $array2 = [ 1182 | 'baz' => 'qux', 1183 | ...$array1 1184 | ]; 1185 | // $array2 = ['baz' => 'qux', 'foo' => 'bar',] 1186 | ``` 1187 | 1188 | Podés desempaquetar la matriz con una clave ya existente: 1189 | 1190 | ```php 1191 | $array1 = ['foo' => 'bar']; 1192 | $array2 = [ 1193 | 'foo' => 'baz', 1194 | ...$array1 1195 | ]; 1196 | // $array2 = ['foo' => 'bar',] 1197 | ``` 1198 | 1199 | Podés desempaquetar una matriz vacía sin error ni advertencia: 1200 | 1201 | ```php 1202 | $array1 = []; 1203 | $array2 = [ 1204 | ...$array1, 1205 | ...[] 1206 | ]; 1207 | // $array2 = [] 1208 | ``` 1209 | 1210 | ### Argumentos Nombrados 1211 | 1212 | ![php-version-80](https://shields.io/badge/php->=8.0-blue) 1213 | 1214 | Desde PHP 8.0, es posible pasar argumentos por nombre en lugar de su posición. 1215 | 1216 | Considerando una función como esta: 1217 | 1218 | ```php 1219 | function concat(string $first, string $second) : string 1220 | { 1221 | return $first . ' ' . $second; 1222 | } 1223 | $a = concat('foo', 'bar'); 1224 | // $a = 'foo bar' 1225 | ``` 1226 | 1227 | Se puede obtener el mismo resultado con la sintaxis del argumento con nombre: 1228 | 1229 | ```php 1230 | $a = concat(first: 'foo', second: 'bar'); 1231 | // $a = 'foo bar' 1232 | ``` 1233 | 1234 | Se puede llamar con argumentos en un orden diferente: 1235 | 1236 | ```php 1237 | $a = concat(second: 'bar', first: 'foo'); 1238 | // $a = 'foo bar' 1239 | ``` 1240 | 1241 | Se pueden omitir parámetros opcionales: 1242 | 1243 | ```php 1244 | function orGate(bool $option1 = false, bool $option2 = false, bool $option3 = false) : bool 1245 | { 1246 | return $option1 || $option2 || $option3; 1247 | } 1248 | $a = orGate(option3: true); 1249 | // $a = true 1250 | ``` 1251 | 1252 | Pero no podés omitir un argumento obligatorio: 1253 | 1254 | ```php 1255 | $a = concat(second: 'bar'); 1256 | // TypeError: concat(): Argument #1 ($first) not passed 1257 | ``` 1258 | 1259 | Tampoco se pueden incluir argumentos adicionales: 1260 | 1261 | ```php 1262 | $a = concat(first: 'foo', second: 'bar', third: 'baz'); 1263 | // PHP Error: Unknown named parameter $third 1264 | ``` 1265 | 1266 | Los argumentos con nombre también funcionan con el constructor de objetos: 1267 | 1268 | ```php 1269 | Class Foo() 1270 | { 1271 | public function __construct( 1272 | public string $first, 1273 | public string $second 1274 | ) {} 1275 | 1276 | } 1277 | $f = new Foo(first: 'bar', second: 'baz'); 1278 | ``` 1279 | 1280 | #### Variadics con nombre 1281 | 1282 | Se puede utilizar argumentos con nombre con un parámetro variadic: 1283 | 1284 | ```php 1285 | function showParams(string ...$params) : array 1286 | { 1287 | return $params; 1288 | } 1289 | $a = showParams(first: 'foo', second: 'bar', third: 'baz'); 1290 | // $a = ["first" => "foo", "second" => "bar", "third" => "baz"] 1291 | ``` 1292 | 1293 | #### Desempaquetando argumentos con nombre 1294 | 1295 | Se puede desempaquetar una matriz asociativa como argumentos con nombre si las claves coinciden con los nombres de los argumentos: 1296 | 1297 | ```php 1298 | function add(int $a, int $b, int $c) : int 1299 | { 1300 | return $a + $b + $c; 1301 | } 1302 | $array = [ 1303 | "b" => 2, 1304 | "c" => 3 1305 | ]; 1306 | $r = add(1, ...$array); 1307 | // $r = 6 1308 | ``` 1309 | 1310 | El orden de los elementos en la matriz asociativa no importa: 1311 | 1312 | ```php 1313 | function add(int $a, int $b, int $c) : int 1314 | { 1315 | return $a + $b + $c; 1316 | } 1317 | $array = [ 1318 | "c" => 3, 1319 | "b" => 2, 1320 | ]; 1321 | $r = add(1, ...$array); 1322 | // $r = 6 1323 | ``` 1324 | 1325 | Si una clave no coincide con el nombre de un argumento, obtendrás un error: 1326 | 1327 | ```php 1328 | function add(int $a, int $b, int $c) : int 1329 | { 1330 | return $a + $b + $c; 1331 | } 1332 | $array = [ 1333 | "b" => 2, 1334 | "c" => 3, 1335 | "d" => 4, 1336 | ]; 1337 | $r = add(1, ...$array); // PHP Error: Unknown named parameter $d 1338 | ``` 1339 | 1340 | #### Recursos adicionales 1341 | 1342 | - [Named arguments in depth on stitcher's blog](https://stitcher.io/blog/php-8-named-arguments) 1343 | - [Named Parameters on PHP.Watch](https://php.watch/versions/8.0/named-parameters) 1344 | 1345 | ### Funciones flecha 1346 | 1347 | ![php-version-74](https://shields.io/badge/php->=7.4-blue) 1348 | 1349 | Las funciones flecha son una alternativa a las [funciones anónimas](https://www.php.net/manual/es/functions.anonymous.php) usando una sintaxis mas corta. El objetivo principal es reducir la verbosidad cuando sea posible: si solo hay una expresión. 1350 | 1351 | Acá hay un ejemplo de una función simple con una sola expresión: 1352 | 1353 | ```php 1354 | $foo = function ($bar) { 1355 | return $bar + 1; 1356 | } 1357 | $a = $foo(1); 1358 | // $a = 2 1359 | ``` 1360 | 1361 | Podés escribir la misma función usando una función flecha: 1362 | 1363 | ```php 1364 | $foo = fn ($bar) => $bar + 1; 1365 | $a = $foo(1); 1366 | // $a = 2 1367 | ``` 1368 | 1369 | No le podés asignar un nombre a una función flecha: 1370 | 1371 | ```php 1372 | fn foo($bar) => $bar + 1; 1373 | // PHP Parse error: Syntax error, unexpected T_STRING, expecting '(' 1374 | ``` 1375 | 1376 | Podés usar una función flecha como un parámetro. Por ejemplo, como un parámetro "invocable" en [array_reduce](https://www.php.net/manual/es/function.array-reduce.php): 1377 | 1378 | ```php 1379 | $myArray = [10,20,30]; 1380 | 1381 | $total = array_reduce($myArray, fn ($carry, $item) => $carry + $item, 0); 1382 | // $total = 60 1383 | ``` 1384 | 1385 | Se permite la sugerencia de tipo como en una función normal: 1386 | 1387 | ```php 1388 | fn (int $foo): int => $foo; 1389 | ``` 1390 | 1391 | No es necesario usar `return` ya que no está permitido: 1392 | 1393 | ```php 1394 | fn ($foo) => return $foo; 1395 | // PHP Parse error: Syntax error, unexpected T_RETURN 1396 | ``` 1397 | 1398 | #### Ámbito exterior 1399 | 1400 | La función flecha requiere la palabra clave `use` para poder acceder a las propiedades desde el ámbito externo: 1401 | 1402 | ```php 1403 | $bar = 10; 1404 | $baz = fn ($foo) => $foo + $bar; 1405 | $a = $baz(1); 1406 | //$a = 11 1407 | ``` 1408 | 1409 | La palabra clave `use` no está permitida: 1410 | 1411 | ```php 1412 | $bar = 10; 1413 | fn ($foo) use ($bar) => $foo + $bar; 1414 | // PHP Parse error: Syntax error, unexpected T_USE, expecting T_DOUBLE_ARROW 1415 | ``` 1416 | 1417 | Podés usar `$this` como en cualquier otra función: 1418 | 1419 | ```php 1420 | fn () => $this->foo + 1; 1421 | ``` 1422 | 1423 | ### Expresión de coincidencia Match 1424 | 1425 | ![php-version-80](https://shields.io/badge/php->=8.0-blue) 1426 | 1427 | Desde PHP 8.0, existe una nueva sintaxis `match` similar a la sintaxis `switch`. Como cada caso coincidente solo debe contener una expresión, no se puede usar y reemplazar una declaración de cambio en cada situación. Sin embargo, es significativamente más corto y más fácil de leer. 1428 | 1429 | La expresión `match` siempre devuelve un valor. Cada condición solo permite una sola expresión, e inmediatamente devuelve el valor y no fallará en las siguientes condiciones sin una declaración explícita de `break`: 1430 | 1431 | ```php 1432 | $foo = 'baz'; 1433 | $a = match($foo) { 1434 | 'bar' => 1, 1435 | 'baz' => 2, 1436 | 'qux' => 3, 1437 | } 1438 | // $a = 2 1439 | ``` 1440 | 1441 | Lanza una excepción cuando el valor no puede coincidir: 1442 | 1443 | ```php 1444 | $foo = 'qux'; 1445 | $a = match($foo) { 1446 | 'bar' => 1, 1447 | 'baz' => 2, 1448 | } 1449 | // PHP Error: Unhandled match value of type string 1450 | ``` 1451 | 1452 | Pero admite una condición predeterminada: 1453 | 1454 | ```php 1455 | $foo = 'qux'; 1456 | $a = match($foo) { 1457 | 'bar' => 1, 1458 | 'baz' => 2, 1459 | default => 3, 1460 | } 1461 | // $a = 3 1462 | ``` 1463 | 1464 | Permite múltiples condiciones en un solo brazo: 1465 | 1466 | ```php 1467 | $foo = 'bar'; 1468 | $a = match($foo) { 1469 | 'bar', 'baz' => 1, 1470 | default => 2, 1471 | } 1472 | // $a = 1 1473 | ``` 1474 | 1475 | Hace una comparación estricta de tipo seguro sin coerción de tipo (es como usar `===` en lugar de `==`): 1476 | 1477 | ```php 1478 | function showType($param) { 1479 | return match ($param) { 1480 | 1 => 'Integer', 1481 | '1' => 'String', 1482 | true => 'Boolean', 1483 | }; 1484 | } 1485 | 1486 | showType(1); // "Integer" 1487 | showType('1'); // "String" 1488 | showType(true); // "Boolean" 1489 | ``` 1490 | 1491 | #### Recurso externo 1492 | 1493 | - [Match expression on PHP.Watch](https://php.watch/versions/8.0/match-expression) 1494 | 1495 | ### Interfaz Stringable 1496 | 1497 | ![php-version-80](https://shields.io/badge/php->=8.0-blue) 1498 | 1499 | Desde PHP 8.0, hay una nueva interfaz llamada `Stringable`, que indica que una clase tiene un método mágico `__toString()`. PHP agrega automáticamente la interfaz `Stringable` a todas las clases que implementan ese método. 1500 | 1501 | ```php 1502 | interface Stringable { 1503 | public function __toString(): string; 1504 | } 1505 | ``` 1506 | 1507 | Cuando se define un parámetro con el tipo `Stringable`, comprobará que la clase dada implementa la interfaz `Stringable`: 1508 | 1509 | ```php 1510 | class Foo { 1511 | public function __toString(): string { 1512 | return 'bar'; 1513 | } 1514 | } 1515 | 1516 | function myFunction(Stringable $param): string { 1517 | return (string) $param; 1518 | } 1519 | $a = myFunction(new Foo); 1520 | // $a = 'bar' 1521 | ``` 1522 | 1523 | Si una clase dada no implementa `__toString()`, obtendrá un error: 1524 | 1525 | ```php 1526 | class Foo { 1527 | } 1528 | 1529 | function myFunction(Stringable $param): string { 1530 | return (string) $param; 1531 | } 1532 | $a = myFunction(new Foo); 1533 | // TypeError: myFunction(): Argument #1 ($param) must be of type Stringable, Foo given 1534 | ``` 1535 | 1536 | Un tipo `Stringable` no acepta `string`: 1537 | 1538 | ```php 1539 | function myFunction(Stringable $param): string { 1540 | return (string) $param; 1541 | } 1542 | $a = myFunction('foo'); 1543 | // TypeError: myFunction(): Argument #1 ($param) must be of type Stringable, string given 1544 | ``` 1545 | 1546 | Por supuesto, para aceptar tanto `string` como `Stringable`, puede usar un tipo de unión: 1547 | 1548 | ```php 1549 | function myFunction(string|Stringable $param): string { 1550 | return (string) $param; 1551 | } 1552 | ``` 1553 | 1554 | ### Enums 1555 | 1556 | ![php-version-81](https://shields.io/badge/php->=8.1-blue) 1557 | 1558 | Un Enum (o enumeración) define un nuevo tipo, que tiene un número fijo y limitado de posibles valores. 1559 | 1560 | ```php 1561 | enum Status 1562 | { 1563 | case DRAFT; 1564 | case PUBLISHED; 1565 | case ARCHIVED; 1566 | } 1567 | ``` 1568 | 1569 | En un Enum, cada definición distingue entre mayúsculas y minúsculas. Históricamente, en PHP generalmente representamos "constantes" con mayúsculas para distinguirlas de las variables normales, por lo que tiene sentido apegarse a la notación en mayúsculas para los casos de enumeración. Tené en cuenta que esto funcionará y definirá 3 casos diferentes: 1570 | 1571 | ```php 1572 | enum MyEnum 1573 | { 1574 | case FOO; 1575 | case foo; 1576 | case Foo; 1577 | } 1578 | ``` 1579 | 1580 | Ahora podés comparar fácilmente las enumeraciones con el tipo de operador seguro `===`: 1581 | 1582 | ```php 1583 | $statusA = Status::PENDING; 1584 | if ($statusA === Status::PENDING) { 1585 | // true 1586 | } 1587 | ``` 1588 | 1589 | Además, una enumeración se comporta como un objeto PHP tradicional: 1590 | 1591 | ```php 1592 | $statusA = Status::PENDING; 1593 | $statusB = Status::PENDING; 1594 | $statusC = Status::ARCHIVED; 1595 | $statusA === $statusB; // true 1596 | $statusA === $statusC; // false 1597 | $statusC instanceof Status; // true 1598 | ``` 1599 | 1600 | Podés usar Enum para hacer cumplir los tipos: 1601 | 1602 | ```php 1603 | function myFunction(Status $param) 1604 | { 1605 | return $param; 1606 | } 1607 | $a = myFunction(Status::DRAFT); 1608 | // $a = Status::DRAFT 1609 | $b = myFunction('foo'); // TypeError: myFunction(): Argument #1 ($param) must be of type Status, string given 1610 | ``` 1611 | 1612 | ### Métodos en Enum 1613 | 1614 | Podés definir métodos en un Enum: 1615 | 1616 | ```php 1617 | enum Status 1618 | { 1619 | case DRAFT; 1620 | case PUBLISHED; 1621 | 1622 | public function label(): string 1623 | { 1624 | return match($this) 1625 | { 1626 | Status::DRAFT => 'Not ready...', 1627 | Status::PUBLISHED => 'Published !', 1628 | }; 1629 | } 1630 | } 1631 | ``` 1632 | 1633 | Entonces podés usar los métodos en cualquier instancia de enum: 1634 | 1635 | ```php 1636 | $a = Status::DRAFT; 1637 | $a->label(); // 'Not ready...' 1638 | ``` 1639 | 1640 | ### Valores de respaldo 1641 | 1642 | A veces es necesario asignar un valor propio a cada caso (ej: para almacenarlo en una base de datos, comparación, etc). Tenés que definir el tipo del valor. Acá hay un ejemplo con un valor definido como un `int` : 1643 | 1644 | ```php 1645 | enum HttpStatus: int 1646 | { 1647 | case OK = 200; 1648 | case NOT_FOUND = 404; 1649 | case INTERNAL_SERVER_ERROR = 500; 1650 | } 1651 | ``` 1652 | 1653 | Y acá hay un ejemplo de un valor definido como `string`: 1654 | 1655 | ```php 1656 | enum Status: string 1657 | { 1658 | case DRAFT = 'draft'; 1659 | case PUBLISHED = 'published'; 1660 | } 1661 | ``` 1662 | 1663 | #### Recursos externos 1664 | 1665 | - [Manual de Enums en la documentación oficial de PHP](https://www.php.net/manual/es/language.enumerations.php) 1666 | - [Enums en PHP.Watch](https://php.watch/versions/8.0/match-expression) 1667 | - [Guía de estilo para Enums en stitcher's blog](https://stitcher.io/blog/php-enum-style-guide) -------------------------------------------------------------------------------- /translations/pt-BR.md: -------------------------------------------------------------------------------- 1 | # Moderno PHP Cheatsheet 2 | 3 | ![Moderno PHP Cheatsheet](https://i.imgur.com/2STEtgG.png) 4 | 5 | 6 | > Se você gostar desse conteudo, você pode me chamar ou me seguir twitter :+1: 7 | 8 | [![Tweet for help](https://img.shields.io/twitter/follow/smknstd?label=Tweet%20%40smknstd&style=social)](https://twitter.com/smknstd/) 9 | 10 | Traduzido por: [Daniel Lemes](https://github.com/lemesdaniel) 11 | > **Nota da tradução** Optei por não traduzir alguns termos por serem extremanento técnicos e poderia prejudicar em uma futura pesquisa do leitor, no entanto sinta-se a vontade para submeter uma PR se achar algum termo melhor e que seja de fácil entendimento 12 | 13 | ## Introdução 14 | 15 | ### Motivação 16 | 17 | Este documento é um cheatsheet para PHP você encontrará essas dicas em projetos e exemplos de códigos modernos. 18 | 19 | Esse guia não tem intenção de ensinar PHP desde do início, mas ajudar denvolvedor com conhecimento básicos mas que tem dificuldades com projetos/frameworks modernos (como Laravel ou Symfony) devidos aos novos conceitos e características introduzidas ao PHP nos últimos anos. 20 | 21 | > **Nota:** Os conceitos aqui introduzidos são baseados na versão mais recente disponível do PHP ([PHP 8.0](https://www.php.net/releases/8.0/en.php) desde da última atualização) 22 | 23 | ### Recursos complementares 24 | 25 | Quando tiver dificuldade em entender algum conceito, eu sugiro que você busque respostas nos seguintes sites: 26 | - [Stitcher's blog](https://stitcher.io/blog) 27 | - [php.Watch](https://php.watch/versions) 28 | - [PHP The Right Way](https://phptherightway.com/) 29 | - [StackOverflow](https://stackoverflow.com/questions/tagged/php) 30 | 31 | ## Sumário 32 | 33 | - [Moderno PHP cheatsheet](#moderno-php-cheatsheet) 34 | * [Introdução](#introdução) 35 | + [Motivação](#motivação) 36 | + [Recursos complementares](#recursos-complementares) 37 | * [Sumário](#sumario) 38 | * [Notions](#notions) 39 | + [Valor padrão para um parâmetro de uma função](#valor-padrão-para-um-parâmetro-de-uma-função) 40 | + [Declaração de tipo](#declaração-de-tipo) 41 | + [Destructuring arrays](#destructuring-arrays) 42 | + [Null Coalescing](#null-coalescing) 43 | + [Nullsafe operator](#nullsafe-operator) 44 | + [Spread operator](#spread-operator) 45 | 46 | ## Notions 47 | 48 | ### Valor padrão para o parâmetro de uma função 49 | 50 | Você pode definir um valor padrão para o parâmetro de uma função: 51 | 52 | ```php 53 | function myFunction($param = 'foo') 54 | { 55 | return $param; 56 | } 57 | $a = myFunction(); 58 | // $a = 'foo' 59 | 60 | $b = myFunction('bar'); 61 | // $b = 'bar' 62 | ``` 63 | Mas se você enviar um valor null ou undefined, o valor padrão será ignorado: 64 | 65 | ```php 66 | function myFunction($param = 'foo') 67 | { 68 | return $param; 69 | } 70 | $a = myFunction(null); 71 | // $a = null 72 | 73 | $b = myFunction($undefined); // PHP Warning: Undefined variable $undefined 74 | // $b = null 75 | ``` 76 | 77 | ### Declaração de tipo 78 | 79 | ![php-version-70](https://shields.io/badge/php->=7.0-blue) 80 | 81 | Com declaração de tipo você pode especificar o tipo de dado que uma propriedade irá receber e força-lo em rempo de execução. Isso funciona tanto com scalar types (int, string, bool, and float) como também array, iterable, object, stdClass, etc. 82 | 83 | Você pode definir o tipo de um parâmetro de uma função: 84 | 85 | ```php 86 | function myFunction(int $param) 87 | { 88 | return $param; 89 | } 90 | $a = myFunction(10); 91 | // $a = 10 92 | $b = myFunction('foo'); // TypeError: myFunction(): Argument #1 ($param) must be of type int, string given 93 | ``` 94 | 95 | Você também pode definir o tipo de retorno de uma função: 96 | 97 | ```php 98 | function myFunction() : int 99 | { 100 | return 'foo'; 101 | } 102 | $a = myFunction(); // TypeError: myFunction(): Return value must be of type int, string returned 103 | ``` 104 | 105 | Quando uma função não deve devolver nada, você pode definir o tipo de retorno como void: 106 | 107 | ```php 108 | function myFunction() : void 109 | { 110 | return 'foo'; 111 | } 112 | // PHP Fatal error: A void function must not return a value 113 | ``` 114 | 115 | Nesse caso tamnbém não se pode devolver nulo: 116 | 117 | ```php 118 | function myFunction() : void 119 | { 120 | return null; 121 | } 122 | // PHP Fatal error: A void function must not return a value 123 | ``` 124 | 125 | Entretanto, o uso de return para sair da função é válido e não irá disparar em um erro: 126 | 127 | ```php 128 | function myFunction() : void 129 | { 130 | return; 131 | } 132 | $a = myFunction(); 133 | // $a = null 134 | ``` 135 | 136 | #### Class property 137 | 138 | ![php-version-74](https://shields.io/badge/php->=7.4-blue) 139 | 140 | Você pode definir o tipo de retorno de uma propriedade de uma classe: 141 | 142 | ```php 143 | Class Foo() 144 | { 145 | public int $bar; 146 | } 147 | $f = new Foo(); 148 | $f->bar = 'baz'; // TypeError: Cannot assign string to property Foo::$bar of type int 149 | ``` 150 | 151 | #### Union type 152 | 153 | ![php-version-80](https://shields.io/badge/php->=8.0-blue) 154 | 155 | Você pode usar uma "união de tipo" para aceitar tipos diferentes, ao invés de um único: 156 | 157 | ```php 158 | function myFunction(string|int|array $param) : string|int|array 159 | { 160 | return $param; 161 | } 162 | ``` 163 | 164 | Isso também funciona com atributos de classes: 165 | 166 | ```php 167 | Class Foo() 168 | { 169 | public string|int|array $bar; 170 | } 171 | ``` 172 | 173 | #### Nullable type 174 | 175 | ![php-version-71](https://shields.io/badge/php->=7.1-blue) 176 | 177 | Quando um parâmetro não tem tipo, pode-se aceitar nulo: 178 | 179 | ```php 180 | function myFunction($param) 181 | { 182 | return $param; 183 | } 184 | $a = myFunction(null); 185 | // $a = null 186 | ``` 187 | 188 | Mas quando um parâmetro é tipado, ao tentar inserir um valor nulo teremos um erro: 189 | 190 | ```php 191 | function myFunction(string $param) 192 | { 193 | return $param; 194 | } 195 | $a = myFunction(null); // TypeError: myFunction(): Argument #1 ($param) must be of type string, null given 196 | ``` 197 | 198 | Se a função tem um tipo de retorno, também não será aceito um retorno nulo 199 | ```php 200 | function myFunction() : string 201 | { 202 | return null; 203 | } 204 | $a = myFunction(); // TypeError: myFunction(): Return value must be of type string, null returned 205 | ``` 206 | 207 | É possível fazer uma declaração onde é permitido receber null 208 | 209 | ```php 210 | function myFunction(?string $param) 211 | { 212 | return $param; 213 | } 214 | $a = myFunction(null); 215 | // $a = null 216 | ``` 217 | 218 | ou com união de tipos (union type): 219 | 220 | ```php 221 | function myFunction(string|null $param) 222 | { 223 | return $param; 224 | } 225 | $a = myFunction(null); 226 | // $a = null 227 | ``` 228 | 229 | Isso também funciona com retornos de função 230 | 231 | ```php 232 | function myFunction(?string $param) : ?string 233 | { 234 | return $param; 235 | } 236 | // or 237 | function myFunction(string|null $param) : string|null 238 | { 239 | return $param; 240 | } 241 | ``` 242 | 243 | Funções que retornam void não podem retornar null: 244 | 245 | ```php 246 | function myFunction() : ?void 247 | { 248 | // some code 249 | } 250 | // PHP Fatal error: Void type cannot be nullable 251 | ``` 252 | 253 | ou 254 | 255 | ```php 256 | function myFunction() : void|null 257 | { 258 | // some code 259 | } 260 | // PHP Fatal error: Void type cannot be nullable 261 | ``` 262 | 263 | Pode-se definir null para uma propriedade de uma classe: 264 | 265 | ```php 266 | Class Foo() 267 | { 268 | public int|null $bar; 269 | } 270 | $f = new Foo(); 271 | $f->bar = null; 272 | $a = $f->bar; 273 | // $a = null 274 | ``` 275 | 276 | ### Destructuring arrays 277 | 278 | Pode-se desestruturar um array para extrair seus elementos em variáveis. 279 | 280 | #### Indexed array 281 | 282 | ![php-version-40](https://shields.io/badge/php->=4.0-blue) 283 | 284 | Considerando um array indexado : 285 | 286 | ```php 287 | $array = ['foo', 'bar', 'baz']; 288 | ``` 289 | 290 | Pode-se desestruturar com list: 291 | 292 | ```php 293 | list($a, $b, $c) = $array; 294 | 295 | // $a = 'foo' 296 | // $b = 'bar' 297 | // $c = 'baz' 298 | ``` 299 | 300 | Ou desde PHP 7.1, a sintaxe curta (shorthand syntax): 301 | 302 | ```php 303 | [$a, $b, $c] = $array; 304 | 305 | // $a = 'foo' 306 | // $b = 'bar' 307 | // $c = 'baz' 308 | ``` 309 | 310 | Você pode pular elementos: 311 | 312 | ```php 313 | list(, , $c) = $array; 314 | 315 | // $c = 'baz' 316 | ``` 317 | 318 | Ou desde PHP 7.1, a sintaxe curta (shorthand syntax): 319 | 320 | ```php 321 | [, , $c] = $array; 322 | 323 | // $c = 'baz' 324 | ``` 325 | 326 | Quando tentamos desestruturar um indexe inexistente recebemos um aviso (warning) e um valor null é lançado nessa posição: 327 | 328 | ```php 329 | list($a, $b, $c, $d) = $array; // PHP Warning: Undefined array key 3 330 | 331 | // $a = 'foo' 332 | // $b = 'bar' 333 | // $c = 'baz' 334 | // $d = null; 335 | ``` 336 | 337 | #### Associative array 338 | 339 | ![php-version-71](https://shields.io/badge/php->=7.1-blue) 340 | 341 | Em array associativos (string-keyed) : 342 | 343 | ```php 344 | $array = [ 345 | 'foo' => 'value1', 346 | 'bar' => 'value2', 347 | 'baz' => 'value3', 348 | ]; 349 | ``` 350 | 351 | A sintaxe utilizando lista não irá funcionar e um aviso (warning) será lançado 352 | 353 | ```php 354 | list($a, $b, $c) = $array; // PHP Warning: Undefined array key 0 ... 355 | 356 | // $a = null 357 | // $b = null 358 | // $c = null 359 | ``` 360 | 361 | Mas desde PHP 7.1.0 (~ dec 2016), você pode desestruturar com uma sintaxe baseada nas chaves: 362 | 363 | ```php 364 | list('foo' => $a, 'bar' => $b, 'baz' => $c) = $array; 365 | 366 | // $a = 'value1' 367 | // $b = 'value2' 368 | // $c = 'value3' 369 | ``` 370 | 371 | Ou com a sintaxe curta (shorthand syntax): 372 | 373 | ```php 374 | ['foo' => $a, 'bar' => $b, 'baz' => $c] = $array; 375 | 376 | // $a = 'value1' 377 | // $b = 'value2' 378 | // $c = 'value3' 379 | ``` 380 | 381 | Podemos também desestruturar apenas uma parte do array (sem que a ordem importe) 382 | 383 | ```php 384 | ['baz' => $c, 'foo' => $a] = $array; 385 | 386 | // $a = 'value1' 387 | // $c = 'value3' 388 | ``` 389 | 390 | Quando tentamos desestruturar uma chave que não exista no array, recebemos um aviso (warning): 391 | 392 | ```php 393 | list('moe' => $d) = $array; // PHP Warning: Undefined array key "moe" 394 | 395 | // $d = null 396 | ``` 397 | 398 | ### Null Coalescing 399 | 400 | ![php-version-70](https://shields.io/badge/php->=7.0-blue) 401 | 402 | Desde de PHP 7.0 (~ dec 2015), você pode usar o operador null coalescing para atribuir um valor no caso de variáveis/propriedades nulas sem que seja emitidos avisos ou erros: 403 | 404 | ```php 405 | $a = null; 406 | $b = $a ?? 'fallback'; 407 | 408 | // $b = 'fallback' 409 | ``` 410 | 411 | Isso é equivalente a: 412 | 413 | ```php 414 | $a = null; 415 | $b = isset($a) ? $a : 'fallback'; 416 | // $b = 'fallback' 417 | ``` 418 | 419 | Isso também funciona quando a variável não for definida: 420 | 421 | ```php 422 | $a = $undefined ?? 'fallback'; 423 | 424 | // $a = 'fallback' 425 | ``` 426 | 427 | 428 | Qualquer outro valor será aceito e não será definido em fallback: 429 | 430 | ```php 431 | '' ?? 'fallback'; // '' 432 | 0 ?? 'fallback'; // 0 433 | false ?? 'fallback'; // false 434 | ``` 435 | 436 | Podemos encadear multiplos null coalescing: 437 | 438 | ```php 439 | $a = null; 440 | $b = null; 441 | $c = $a ?? $b ?? 'fallback'; 442 | // $c = 'fallback' 443 | ``` 444 | 445 | #### Elvis operator 446 | 447 | ![php-version-53](https://shields.io/badge/php->=5.3-blue) 448 | 449 | Não deve ser confundido com o operador ternário (aka the elvis operator), que foi introduzido no PHP 5.3: 450 | 451 | ```php 452 | $a = null; 453 | $b = $a ?: 'fallback'; 454 | 455 | // $b = 'fallback' 456 | ``` 457 | 458 | A opção equivalente do operador ternário é: 459 | 460 | ```php 461 | $a = null; 462 | $b = $a ? $a : 'fallback'; 463 | // $b = 'fallback' 464 | ``` 465 | 466 | O resultado entre null coalescing e elvis operator podem ser similares, mas também diferente para algumas situações específicas: 467 | 468 | ```php 469 | '' ?: 'fallback'; // 'fallback' 470 | 0 ?: 'fallback'; // 'fallback' 471 | false ?: 'fallback'; // 'fallback' 472 | ``` 473 | 474 | #### Null coalescing on array 475 | 476 | Se a chave de um array existe, o fallback não é chamado: 477 | 478 | ```php 479 | $a = ['foo' => 'bar']; 480 | $b = $a['foo'] ?? 'fallback'; 481 | 482 | // $b = 'bar' 483 | ``` 484 | 485 | Mas quando o array não existe, fallback é chamado sem emitir erros ou avisos: 486 | 487 | ```php 488 | $a = null; 489 | $b = $a['foo'] ?? 'fallback'; 490 | 491 | // $b = 'fallback' 492 | ``` 493 | 494 | Ou a propriedade de um array é indefinida, fallback é chamado sem emitir erros ou avisos: 495 | 496 | ```php 497 | $b = $undefined['foo'] ?? 'fallback'; 498 | 499 | // $b = 'fallback' 500 | ``` 501 | 502 | Quando o array existe mas a chave não, fallback é chamado sem emitir erros ou avisos: 503 | 504 | ```php 505 | $a = []; 506 | $b = $a['foo'] ?? 'fallback'; 507 | 508 | // $b = 'fallback' 509 | ``` 510 | 511 | 512 | Isso também funciona com arrays indexados: 513 | 514 | ```php 515 | $a = ['foo']; 516 | 517 | // reminder: $a[0] = 'foo' 518 | 519 | $b = $a[1] ?? 'fallback'; 520 | 521 | // $b = 'fallback' 522 | ``` 523 | 524 | Isso também funciona com array multi dimensionais. Se a chave existir, fallback não é chamado: 525 | 526 | ```php 527 | $a = [ 528 | 'foo' => [ 529 | 'bar' => 'baz' 530 | ] 531 | ]; 532 | $b = $a['foo']['bar'] ?? 'fallback'; 533 | 534 | // $b = 'baz' 535 | ``` 536 | 537 | Mas em arrays multi dimensionais quando a chave não existir, fallback é chamado sem emitir erros ou avisos: 538 | 539 | ```php 540 | $a = [ 541 | 'foo' => [ 542 | 'bar' => 'baz' 543 | ] 544 | ]; 545 | $b = $a['foo']['qux'] ?? 'fallback'; 546 | 547 | // $b = 'fallback' 548 | ``` 549 | 550 | #### Null coalescing on object 551 | 552 | 553 | Você também pode usar null operador coalescing com objetos. 554 | 555 | ##### Object's attribute 556 | 557 | If object's attribute exists, then fallback isn't triggered: 558 | Se a propriedade do objeto existir, fallback não é chamado: 559 | 560 | ```php 561 | $a = (object)[ 562 | 'foo' => 'bar' 563 | ]; 564 | $b = $a->foo ?? 'fallback'; 565 | 566 | // $b = 'bar' 567 | ``` 568 | 569 | mas se a propriedade do objeto não for encontrada, fallback é chamado sem emitir erros ou avisos: 570 | 571 | ```php 572 | $a = (object)[ 573 | 'foo' => 'bar' 574 | ]; 575 | $b = $a->baz ?? 'fallback'; 576 | 577 | // $b = 'fallback' 578 | ``` 579 | 580 | ##### Object's method 581 | 582 | Você também pode usar o operador null coalescing ao chamar métodos. Se ele existir, fallback é ignorado. 583 | 584 | 585 | ```php 586 | class Foo 587 | { 588 | public function bar() 589 | { 590 | return 'baz'; 591 | } 592 | } 593 | 594 | $a = new Foo(); 595 | $b = $a->bar() ?? 'fallback'; 596 | 597 | // $b = 'baz' 598 | ``` 599 | 600 | Mas quando o método retornar null, fallback é chamado sem emitir erros ou avisos: 601 | 602 | ```php 603 | class Foo 604 | { 605 | public function bar() 606 | { 607 | return null; 608 | } 609 | } 610 | 611 | $a = new Foo(); 612 | $b = $a->bar() ?? 'fallback'; 613 | 614 | // $b = 'fallback' 615 | ``` 616 | 617 | Se o método não for encontrado na classe, null coalescing não funcionará e um erro será lançado: 618 | 619 | ```php 620 | class Foo 621 | { 622 | public function bar() 623 | { 624 | return 'baz'; 625 | } 626 | } 627 | 628 | $a = new Foo(); 629 | $b = $a->baz() ?? 'fallback'; // PHP Error: Call to undefined method baz() 630 | ``` 631 | 632 | ##### Chained method 633 | 634 | Quando usamos métodos encadeados um método intermediário retornar null, o operador null coalescing não funcionará e um erro será lançado: 635 | 636 | ```php 637 | class Foo 638 | { 639 | public function bar() 640 | { 641 | return (object)[]; 642 | } 643 | } 644 | 645 | $a = new Foo(); 646 | $b = $a->bar()->baz() ?? 'fallback'; // PHP Error: Call to undefined method baz() 647 | ``` 648 | 649 | #### Null Coalescing Assignment operator 650 | 651 | ![php-version-74](https://shields.io/badge/php->=7.4-blue) 652 | 653 | 654 | Você pode definidir um valor padrão quando o valor for null 655 | 656 | ```php 657 | $a = null; 658 | $a = $a ?? 'foo'; 659 | // $a = 'foo' 660 | ``` 661 | 662 | Desde de PHP 7.4, você pode usar o operador null coalescing para fazer o mesmo: 663 | 664 | ```php 665 | $a = null; 666 | $a ??= 'foo'; 667 | // $a = 'foo' 668 | ``` 669 | 670 | ### Operador Nullsafe 671 | 672 | ![php-version-80](https://shields.io/badge/php->=8.0-blue) 673 | 674 | Ao tentar ler uma propriedade ou um chamar um método null, você receberá um aviso e um erro: 675 | 676 | ```php 677 | $a = null; 678 | $b = $a->foo; // PHP Warning: Attempt to read property "foo" on null 679 | // $b = null 680 | 681 | $c = $a->foo(); // PHP Error: Call to a member function foo() on null 682 | ``` 683 | Com o operador nullsafe, você pode fazer sem receber erros ou avisos 684 | 685 | ```php 686 | $a = null; 687 | $b = $a?->foo; 688 | // $b = null 689 | $c = $a?->foo(); 690 | // $c = null 691 | ``` 692 | 693 | Você pode encadear multiplos operadores nullsafe: 694 | 695 | ```php 696 | $a = null; 697 | $b = $a?->foo?->bar; 698 | // $b = null 699 | $c = $a?->foo()?->bar(); 700 | // $c = null 701 | ``` 702 | 703 | Uma expressão é um short-circuited do primeiro operador null-safe encontrado: 704 | 705 | ```php 706 | $a = null; 707 | $b = $a?->foo->bar->baz(); 708 | // $b = null 709 | ``` 710 | 711 | Operador Nullsafe não tem efeito em valores não nulos. 712 | 713 | ```php 714 | $a = 'foo'; 715 | $b = $a?->bar; // PHP Warning: Attempt to read property "bar" on string 716 | // $b = null 717 | $c = $a?->baz(); // PHP Error: Call to a member function baz() on string 718 | ``` 719 | 720 | Operador Nullsafe não consegue trabalhar adequadamente com arrays, mesmo assim tem algum efeito: 721 | 722 | ```php 723 | $a = []; 724 | $b = $a['foo']->bar; 725 | // PHP Warning: Undefined array key "foo" 726 | // PHP Warning: Attempt to read property "bar" on null 727 | // $b = null 728 | 729 | $c = $a['foo']?->bar; // PHP Warning: Undefined array key "foo" 730 | // $c = null 731 | 732 | $d = $a['foo']->bar(); 733 | // PHP Warning: Undefined array key "foo" 734 | // PHP Error: Call to a member function bar() on null 735 | 736 | $e = $a['foo']?->bar(); // PHP Warning: Undefined array key "foo" 737 | // $e = null 738 | ``` 739 | 740 | Você não pode usar o operador nullsafe em operações de escrita, ele é apenas um recurso de leitura: 741 | 742 | ```php 743 | $a = null; 744 | $a?->foo = 'bar'; // PHP Fatal error: Can't use nullsafe operator in write context 745 | ``` 746 | 747 | ### Spread operator 748 | 749 | #### Variadic parameter 750 | 751 | ![php-version-56](https://shields.io/badge/php->=5.6-blue) 752 | 753 | Desde do PHP 5.6 (~ aug 2014), você pode adicionar uma lista de parâmetros com tamanho indefinido ou variáveis: 754 | 755 | ```php 756 | function countParameters(string $param, string ...$options) : int 757 | { 758 | 759 | foreach ($options as $option) { 760 | // you can iterate on $options 761 | } 762 | 763 | return 1 + count($options); 764 | } 765 | 766 | countParameters('foo'); // 1 767 | countParameters('foo', 'bar'); // 2 768 | countParameters('foo', 'bar', 'baz'); // 3 769 | ``` 770 | 771 | Parâmetros variáveis devem ser semre o último parâmetros declarados: 772 | 773 | ```php 774 | function countParameters(string ...$options, string $param) 775 | { 776 | // some code 777 | } 778 | // PHP Fatal error: Only the last parameter can be variadic 779 | ``` 780 | 781 | Você pode ter apenas um parâmetro variável: 782 | 783 | ```php 784 | function countParameters(string ...$options, string ...$moreOptions) 785 | { 786 | // some code 787 | } 788 | // PHP Fatal error: Only the last parameter can be variadic 789 | ``` 790 | 791 | Você não deve ter um valor padrão: 792 | 793 | ```php 794 | function countParameters(string $param, string ...$options = []) 795 | { 796 | // some code 797 | } 798 | // PHP Parse error: Variadic parameter cannot have a default value 799 | ``` 800 | 801 | Quando não tipado, isso aceita qualquer valor: 802 | 803 | ```php 804 | function countParameters(string $param, ...$options) : int 805 | { 806 | return 1 + count($options); 807 | } 808 | 809 | countParameters('foo', null, [], true); // 4 810 | ``` 811 | 812 | Quando tipado, deve-se passar os valores de acordo com o tipo: 813 | 814 | ```php 815 | function countParameters(string $param, string ...$options) : int 816 | { 817 | return 1 + count($options); 818 | } 819 | 820 | countParameters('foo', null); 821 | // TypeError: countParameters(): Argument #2 must be of type string, null given 822 | 823 | countParameters('foo', []); 824 | // TypeError: countParameters(): Argument #2 must be of type string, array given 825 | ``` 826 | 827 | #### Argument unpacking 828 | 829 | ![php-version-56](https://shields.io/badge/php->=5.6-blue) 830 | 831 | Array e objetos podem ser desempacotados em uma lista de argumentos usando spread operator: 832 | 833 | ```php 834 | function add(int $a, int $b, int $c) : int 835 | { 836 | return $a + $b + $c; 837 | } 838 | $array = [2, 3]; 839 | $r = add(1, ...$array); 840 | 841 | // $r = 6 842 | ``` 843 | 844 | O array inserido pode ter mais elementos que o necessário: 845 | 846 | ```php 847 | function add(int $a, int $b, int $c) : int 848 | { 849 | return $a + $b + $c; 850 | } 851 | $array = [2, 3, 4, 5]; 852 | $r = add(1, ...$array); 853 | 854 | // $r = 6 855 | ``` 856 | 857 | O array passando não pode ter menos elementos que o necessário: 858 | 859 | ```php 860 | function add(int $a, int $b, int $c) : int 861 | { 862 | return $a + $b + $c; 863 | } 864 | $array = [2]; 865 | $r = add(1, ...$array); // TypeError: Too few arguments to function add(), 2 passed 866 | ``` 867 | 868 | Exceto quando algum argumento da função tem um valor padrão: 869 | 870 | ```php 871 | function add(int $a, int $b, int $c = 0) : int 872 | { 873 | return $a + $b + $c; 874 | } 875 | $array = [2]; 876 | $r = add(1, ...$array); 877 | // $r = 3 878 | ``` 879 | 880 | Se um argumento é tipado e o valor inserido não é do mesmo tipo, um erro será lançado:\ 881 | 882 | ```php 883 | function add(int $a, int $b, int $c) : int 884 | { 885 | return $a + $b + $c; 886 | } 887 | $array = ['foo', 'bar']; 888 | $r = add(1, ...$array); // TypeError: add(): Argument #2 ($b) must be of type int, string given 889 | ``` 890 | 891 | 892 | É possível passar um array associativo, mas as chaves desses corresponder aos nomes dos argumentos: 893 | 894 | ```php 895 | function add(int $a, int $b, int $c) : int 896 | { 897 | return $a + $b + $c; 898 | } 899 | $array = [ 900 | "b" => 2, 901 | "c" => 3 902 | ]; 903 | $r = add(1, ...$array); 904 | // $r = 6 905 | ``` 906 | 907 | A ordem dos elementos em um array associativos não importa: 908 | 909 | ```php 910 | function add(int $a, int $b, int $c) : int 911 | { 912 | return $a + $b + $c; 913 | } 914 | $array = [ 915 | "c" => 3, 916 | "b" => 2, 917 | ]; 918 | $r = add(1, ...$array); 919 | // $r = 6 920 | ``` 921 | 922 | Se a chave não corresponder a um argumento, um erro será lançado: 923 | 924 | ```php 925 | function add(int $a, int $b, int $c) : int 926 | { 927 | return $a + $b + $c; 928 | } 929 | $array = [ 930 | "b" => 2, 931 | "c" => 3, 932 | "d" => 4, 933 | ]; 934 | $r = add(1, ...$array); // PHP Error: Unknown named parameter $d 935 | ``` 936 | 937 | #### Array unpacking 938 | 939 | ##### Indexed array 940 | 941 | ![php-version-74](https://shields.io/badge/php->=7.4-blue) 942 | 943 | Quando você pretender combinar (unir) vários arrays, normalmente usa-se `array_merge` 944 | 945 | ```php 946 | $array1 = ['baz']; 947 | $array2 = ['foo', 'bar']; 948 | 949 | $array3 = array_merge($array1,$array2); 950 | // $array3 = ['baz', 'foo', 'bar'] 951 | ``` 952 | 953 | Desde de PHP 7.4 (~ nov 2019), você pode desempacotar arrays com spread operator: 954 | 955 | ```php 956 | $array1 = ['foo', 'bar']; 957 | $array2 = ['baz', ...$array1]; 958 | // $array2 = ['baz', 'foo', 'bar'] 959 | ``` 960 | 961 | Elementos são combinados na ordem em que são passados: 962 | 963 | ```php 964 | $array1 = ['foo', 'bar']; 965 | $array2 = ['baz', ...$array1, "qux"]; 966 | // $array2 = ['baz', 'foo', 'bar', "qux"] 967 | ``` 968 | 969 | Não é verificado qualquer valor duplicado: 970 | 971 | ```php 972 | $array1 = ['foo', 'bar']; 973 | $array2 = ['foo', ...$array1]; 974 | // $array2 = ['foo', 'foo', 'bar'] 975 | ``` 976 | 977 | Você pode desempacotar vários arrays ao mesmo tempo: 978 | 979 | ```php 980 | $array1 = ['foo', 'bar']; 981 | $array2 = ['baz']; 982 | $array3 = [ ...$array1, ...$array2]; 983 | // $array3 = ['foo', 'bar', 'baz'] 984 | ``` 985 | 986 | Também podemos desempacotar arrays multiplas vezes: 987 | 988 | ```php 989 | $array1 = ['foo', 'bar']; 990 | $array2 = [ ...$array1, ...$array1]; 991 | // $array2 = ['foo', 'bar', 'foo', 'bar'] 992 | ``` 993 | 994 | Se tentarmos desempacotar um array vazio não será lançado qualquer erro ou aviso: 995 | 996 | ```php 997 | $array1 = []; 998 | $array2 = ['foo', ...$array1]; 999 | // $array2 = ['foo'] 1000 | ``` 1001 | 1002 | Você pode desempacotar um array, que não tenha sido previamente armazenado em uma variável: 1003 | 1004 | ```php 1005 | $array1 = [...['foo', 'bar'], 'baz']; 1006 | // $array1 = ['foo', 'bar', 'baz'] 1007 | ``` 1008 | 1009 | Desempacotar funciona apenas com arrays e objetos. Se você tentar desempacotar quaqluer outro valor, como null, um erro será lançado: 1010 | 1011 | ```php 1012 | $array1 = null; 1013 | $array2 = ['foo', ...$array1]; // PHP Error: Only arrays and Traversables can be unpacked 1014 | ``` 1015 | 1016 | Você também pode desempacotar o resultado de uma função/método: 1017 | 1018 | ```php 1019 | function getArray() : array { 1020 | return ['foo', 'bar']; 1021 | } 1022 | 1023 | $array = [...getArray(), 'baz']; 1024 | // $array = ['foo', 'bar', 'baz'] 1025 | ``` 1026 | --------------------------------------------------------------------------------