Upgrade to Pro — share decks privately, control downloads, hide ads and more …

O Que Há de Novo no PHP 8.0 e 8.1?

O Que Há de Novo no PHP 8.0 e 8.1?

O PHP tem evoluído constantemente nos últimos anos e hoje em dia conta com um robusto ecossistema de ferramentas e funcionalidades. E, em breve, será lançado o PHP 8.1. Ela será uma das releases com um grande número de funcionalidades. Nesta apresentação falaremos sobre as novidades do PHP 8.0 e 8.1 como named arguments, attributes, constructor property promotion, match expressions, enums, array unpacking com chaves em string, readonly properties entre outras novidades.

Marcel dos Santos

November 04, 2021
Tweet

More Decks by Marcel dos Santos

Other Decks in Programming

Transcript

  1. Interaja nas mídias sociais! 
 
 - fale sobre o

    evento, palestrantes e conteúdo - tire fotos do evento e publique 
 - interaja com outros participantes do evento - tire dúvidas ou dê feedbacks para os palestrantes 
 - utilize as hashtags#php80 e #php81
  2. o PHP existe há mais de 20 anos e passou

    por várias "revoluções"
  3. o Composer causou uma transformação na forma como bibliotecas são

    distribuídas e como aplicações PHP são desenvolvidas
  4. na versão 7.0 fi cou de 2 a 3 vezes

    mais rápido e inúmeras funcionalidades foram adicionadas ao core da linguagem
  5. na versão 7.4 foram introduzidas funcionali- dades muito solicitadas como

    propriedades tipadas, arrow functions e spread operator
  6. C om pos e , L ar avel, Symf on

    y, Laminas, Slim, Sil er , CakePHP , Yii, CodeIgnit e , Pr oo ph, Doc tr ine, Guzzle, Respect, PHP League, M on ol og, PHP-DI, FastR ou te, Psl, PHP-DS, Symf on y C om p on ents, Ramsey Uuid, Email Validat o , C ar b on , Flysystem, CLImate, Psysh, Twig, Fak e , Int er venti on Image, Ass er t, Depl oyer , PHPMail e , Magento, W or dPress, Drupal, J oo mla, Sylius, OpenC ar t, W oo C om m er ce, PhpSt or m, Sw oo le, ReactPHP , Amp, Rev ol t PHP , Hyp er f, Octane, Bref, Vap o , XDebug, phpdbg, PHPStan, Psalm, Phan, PHPUnit, Codecepti on , Pest, Infecti on PHP , PHPSpec, Pr op hecy, Mock er y, Behat, PHP CodeSniff e , PHP CS F ixer , PHPMD, PHPCPD, GrumPHP , CaptainH oo k, Dep tr ac, Rect or , phpDocument o , Safe-PHP
  7. a próxima grande novidade do PHP é o lançamento da

    versão 8.1, uma release com muitas novidades
  8. isso fazia com que, para ter essa garantia, houvesse um

    boilerplate desnecessário de código
  9. / / code with unnecessary boilerplate to enforce type contracts

    class User { /** @var int $id * / private $id; /** @var string $name * / private $name; public function _ _ construct(int $id, string $name) { $this - > id = $id; $this - > name = $name; } public function getId() : int { return $this - > id; } / / setId, getName and setName implementation . . . }
  10. / / more concise code with same type contracts class

    User { public int $id; public string $name; public function _ _ construct(int $id, string $name) { $this - > id = $id; $this - > name = $name; } }
  11. se uma propriedade tipada não tiver um valor padrão ela

    será considerada não inicializada
  12. / / uninitialized properties and default null class User {

    public $id; public $name; } $user = new User; var_dump($user); / / class User#1 (2) { / / public $id = > NULL / / public $name = > NULL / / }
  13. / / uninitialized properties and no null default class User

    { public int $id; / / no null default public ?string $name; / / also no null default } $user = new User; var_dump($user); / / object(User)#1 (0) { / / ["id"] = > uninitialized(int) / / ["name"] = > uninitialized(?string) / / }
  14. ao tentar fazer a leitura de uma propriedade não inicializada

    será lançado um erro do tipo TypeError
  15. / / try to access a uninitialized property class User

    { public int $id; public string $name; } $user = new User; echo $user - > id; / / Uncaught Error: Typed property User : : $id must 
 / / not be accessed before initialization
  16. isso ocorre por causa do boilerplate sintático 
 e a

    necessidade de importar as variáveis que serão utilizadas no escopo interno da função
  17. a funcionalidade de arrow functions do PHP 7.4 torna mais

    concisa a sintaxe para esse padrão
  18. ao utilizar uma variável de fi nida no escopo externo

    ela será passada de forma implícita para a expressão
  19. / / variable in parent scope is captured - by

    - value 
 $y = 1; $inc1 = fn($x) = > $x + $y; $inc2 = function ($x) use ($y) { return $x + $y; };
  20. / / arrow functions help reducing code boilerplate 
 /

    / (without arrow functions) $result = Collection : : from([1, 2]) - > map(function ($v) { return $v * 2; }) - > reduce(function ($tmp, $v) { return $tmp + $v; }, 0); echo $result; / / 6
  21. / / arrow functions help reducing code boilerplate / /

    (with arrow functions) 
 $result = Collection : : from([1, 2]) - > map(fn($v) = > $v * 2) - > reduce(fn($tmp, $v) = > $tmp + $v, 0); echo $result; / / 6
  22. a funcionalidade permite o "desempacota- mento" de um array (ou

    um Traversable) em uma lista de argumentos utilizando o spread operator
  23. function sum($a, $b) { return $a + $b; } /

    / using spread operator ( . . . ) to unpacking / / an array as an argument list $numbers = [3, 5]; echo sum( . . . $numbers); / / 8
  24. a utilização do spread operator não era permitido na de

    fi nição de arrays a partir de outro array
  25. / / using spread operator to def i ne a

    new array / / from another is not supported $someNumbers = [2, 3, 4]; $numbers = [1, . . . $someNumbers, 5]; print_r($numbers); 
 / / PHP Parse error: syntax error, unexpected ' . . . ' 
 / / (T_ELLIPSIS), expecting ']'
  26. a nova funcionalidade permite a utilização do spread operator (...)

    na de fi nição de um array através do unpacking dos valores de outro array ou Traversable
  27. / / using spread operator to def i ne an

    array from another $someNames = ['Bob', 'Carol']; $names = ['Alice', . . . $someNames, 'Daniel', 'Elisa']; print_r($names); / / ['Alice', 'Bob', 'Carol', 'Daniel', 'Elisa'];
  28. essa funcionalidade só está disponível para arrays com chaves numéricas

    (para manter consistência com o argument unpacking)
  29. o olho de um ser humano não é otimizado para

    olhar e decodi fi car rapidamente uma sequências de dígitos
  30. a nova funcionalidade numeric literal separator permite usar um separador

    visual para ajudar a melhorar a legibilidade do código e transmitir informações adicionais
  31. / / using numeric literal separator $threshold = 1_000_000_000; /

    / a billion $testValue = 100_925_284.88; / / scale is hundreds of millions $discount = 135_00; / / $135, stored as cents
  32. os argumentos nomeados permitem passar os argumentos para uma função

    com base no nome do parâmetro em vez da posição do parâmetro
  33. os benefícios de usar argumentos nomeados são: -o argumento é

    auto-explicativo -pode ser usado em qualquer posição -pode omitir valores padrões
  34. function greet(string $gretting, string $name, int $number = 1) :

    void { echo "$gretting, $name" . str_repeat('!', $number) . PHP_EOL; } / / using positional and named arguments greet("Hello", "Alice"); / / Hello Alice! greet(gretting: "Hello", name: "Bob"); / / Hello Bob! / / using of out - of - order named arguments greet("Hello", name: "Carol"); / / Hello Carol! greet(name: "Dave", gretting: "Hello", number: 5); / / Hello, Dave!!!!!
  35. os attributes permitem adicionar meta- informações a elementos do código

    como classes, propriedades, métodos, funções, parâmetros e constantes
  36. conceitos similares existem em outras linguagens como annotations em Java,

    attributes em C#, Rust e Hack e decorators em Python e JavaScript
  37. / / using docblock annotations in order to mapping /

    / an entity to database table class User { /** @Column(type="int") * / private int $id; /** @Column(type="string", length=100) * / private int $name; }
  38. agora, como parte da linguagem, os attributes podem ter a

    sintaxe veri fi cada 
 por linters, ferramentas de análise 
 estática e IDEs
  39. outra vantagem é não precisar de uma biblioteca externa para

    realizar o parsing de docblocks para obter as annotations
  40. / / using annotations with built - in attributes class

    User { # [ Column(type: 'integer')] private int $id; # [ Column(type: 'string', length: 100)] private int $name; }
  41. / / route def i nition in Symfony using attributes

    class SomeController { # [ Route('/path', name: 'action')] public function someAction() { / / . . . } }
  42. / / user implementation with excessive boilerplate class User {

    public int $id; public string $name; public string $email; public function _ _ construct( int $id, string $name, string $email ) { $this - > id = $id; $this - > name = $name; $this - > email = $email; } }
  43. $user1 = new User(1, "Alice", "[email protected]"); print_r($user1); / / User

    Object / / ( / / [id] = > 1 / / [name] = > Alice / / [email] = > [email protected] / / )
  44. / / using constructor property promotion / / and with

    no boilerplate class User { public function _ _ construct( public int $id, public string $name, public string $email ) {} }
  45. $user2 = new User(2, "Bob", "[email protected]"); print_r($user2); / / User

    Object / / ( / / [id] = > 2 / / [name] = > Bob / / [email] = > [email protected] / / )
  46. essa funcionalidade pode ser combinada com outras funcionalidades novas e

    reduzir a quantidade de código e torná-lo mais expressivo
  47. o tipo nullable possui a sintaxe ?Type e pode ser

    do tipo Type|null, isto é, Type ou null
  48. declare(strict_types=1); / / using union type to annotate a function

    parameter function power(float|int $number, int $exponent) : int|float { return $number * * $exponent; } echo power(3, 2); / / 9 echo power(3.5, 2); / / 12.25 echo power('3', 2.5); / / Uncaught TypeError: power() : Argument #1 ($number) must be of / / type int|float, string given
  49. o suporte nativo permite a garantia de tipos pelo interpretador

    PHP e reduz a necessida- de de docblocks
  50. no PHP throw é uma instrução e não era possível

    lançar exceções em locais onde apenas expressões são permitidas…
  51. / / trying to throw an exception in an expression

    shows a / / syntax error in PHP 7.4 $function = fn() = > throw new Exception('an exception was thrown'); $function(); / / Parse error: syntax error, unexpected 'throw' (T_THROW) $nullableValue = null; $value = $nullableValue ? ? throw new Exception('null is not allowed'); / / Parse error: syntax error, unexpected 'throw' (T_THROW)
  52. / throwing an exception in an expression $function = fn()

    = > throw new Exception('an exception was thrown'); $function(); / / PHP 8.0 - Fatal error: Uncaught Exception: an exception was thrown $nullableValue = null; $value = $nullableValue ? ? throw new Exception('null is not allowed'); / / PHP 8.0 - Fatal error: Uncaught Exception: null is not allowed
  53. porém, o switch tem os seguintes problemas: - esquecer a

    atribuição da variável em algum dos casos 
 - possuir um boilerplate execessivo
  54. / / switch has an excessive boilerplate and is error

    prone switch ($statusCode) { case 200 : $reasonPhrase = 'Ok'; break; case 201 : $reasonPhrase = 'Created'; break; case 400 : $reasonPhrase = 'Bad Request'; break; } echo $result; / / Created
  55. / / match is less verbose and more expressive echo

    match ($statusCode) { 200 = > 'Ok', 201 = > 'Created', 400 = > 'Bad Request', }; / / Created
  56. o match utiliza a comparação estrita (===) e leva a

    uma avaliação mais previsível independente do uso de strict_types
  57. / / match with multiple conditions for the same branch

    echo match($country) { 'brazil', 'portugal' = > 'portuguese', 'argentina', 'spain', 'mexico' = > 'spanish', default = > 'another language' }; / / portuguese
  58. caso não exista uma branch correspondente ao resultado da expressão

    a exceção UnhandledMatchError será lançada
  59. uma enum de fi ne um novo tipo que possui

    número fi xo e limitado de valores possíveis
  60. / / creates an enum for the suits of a

    deck enum Suit { case Hearts; case Diamonds; case Clubs; case Spades; } $value = Suit : : Hearts; var_dump($value); / / enum(Suit : : Hearts)
  61. esse tipo de valor é chamado de pure case e

    uma enum que contém apenas pure cases é chamada de pure enum
  62. / / annotate a function parameter with an enum type

    function pick_a_card(Suit $suit) {} pick_a_card($value); / / ok pick_a_card(Suit : : Clubs); / / ok pick_a_card('Spades'); / / Fatal error: Uncaught TypeError: pick_a_card() : Argument #1 ($suit) must be of type Suit, string given
  63. contudo, existem casos de usos em que é necessário ter

    equivalentes escalares para, por exemplo, persistir em uma base de dados
  64. / / create an enum backed with scalar values enum

    Suit: string { case Hearts = 'H'; case Diamonds = 'D'; case Clubs = 'C'; case Spades = 'S'; } var_dump(Suit : : Hearts); / / enum(Suit : : Hearts) var_dump(Suit : : Hearts - > name); / / string(6) "Hearts" var_dump(Suit : : Hearts - > value); / / string(1) "H"
  65. um case que possui um equivalente escalar é chamado de

    backed case pois é "suportado" por um valor mais simples
  66. um backed enum implementa a interface interna BackedEnum que expõe

    dois méto- dos adicionais que são from e tryFrom
  67. o método from() recebe um tipo escalar e retorna o

    case correspondente e, caso o valor não seja encontrado, a exceção ValueError é lançada
  68. / / create an order status enum enum OrderStatus: string

    { case PendingPayment = 'pending_payment'; case Processing = 'processing'; case Completed = 'completed'; case Refunded = 'refunded'; case Cancelled = 'cancelled'; }
  69. / / create an enum value using from() method with

    a valid value $orderStatus = OrderStatus : : from('processing'); var_dump($orderStatus); / / enum(OrderStatus : : Processing) echo $orderStatus - > value; / / processing / / try to create an enum value using from() method with an invalid value $orderStatus = OrderStatus : : from('non_existent'); / / Fatal error: Uncaught ValueError: "non_existent" is not a / / valid backing value for enum "OrderStatus" / / try to create an enum value using tryFrom() method with an invalid value $orderStatus = OrderStatus : : tryFrom('non_existent'); var_dump($orderStatus); / / null
  70. o PHP 7.4 tinha adicionado suporte para o unpacking de

    arrays em outros arrays utilizando o spread operator
  71. porém, não era permitido o unpacking de arrays com chaves

    em string devido: (1) incertezas em relação a semântica e (2) limitações no argument unpacking
  72. / / using array unpacking with string keys $user1 =

    ['name' = > 'Alice']; $user2 = ['name' = > 'Bob']; / / array unpacking with string keys in PHP 8.0 returns an error var_dump(array_merge($user1, $user2)); / / ["name" = > "Bob"] var_dump([ . . . $user1, . . . $user2]); / / Fatal error: Uncaught Error: Cannot unpack array with string keys / / array unpacking with string keys in PHP 8.1 var_dump(array_merge($user1, $user2)); / / ["name" = > "Bob"] var_dump([ . . . $user1, . . . $user2]); / / ["name" = > "Bob"]
  73. com o suporte a essa funcionalidade é possível combinar as

    funcionalidades de argument unpacking e named arguments
  74. / / combine argument unpacking with named arguments function greet(string

    $greeting, string $name) : void { echo "$greeting, $name!" . PHP_EOL; } greet('Hi', 'Alice'); / / Hi, Alice! greet('Bonjour', 'Bob'); / / Bonjour, Bob! greet(greeting: 'Hallo', name: 'Carol'); / / Hallo, Carol! greet( . . . ['name' = > 'David', 'greeting' = > 'Konichiwa']); / / Konichiwa David!
  75. os objetos de valores são imutáveis, isto é, as propriedades

    são inicializadas no construtor e não podem ser alteradas depois
  76. / / create an email value object and exposes a

    getter method class Email { public function _ _ construct( private string $value ) { / / throws an exception if the email is not valid $this - > value = $value; } public function value() : string { return $this - > value; } }
  77. / / create an email value object with less boilerplate

    class Email { public function _ _ construct( public readonly string $value ) { / / throws an exception if the email is not valid $this - > value = $value; } } $email = new Email('[email protected]'); echo($email - > value); / / [email protected] $email - > value = '[email protected]'; / / Uncaught Error: Cannot modify readonly property Email : : $value
  78. uma propriedade readonly só pode ser inicializada uma vez e

    somente no escopo em que ela foi declarada
  79. / / create closures with both old and new syntax

    $strlen1 = Closure : : fromCallable('strlen'); $strlen2 = strlen( . . . );
  80. essa sintaxe é mais expressiva, acessível a ferramentas de análise

    estática e respeita o escopo em que foi criada
  81. uma função ou método declarados com o tipo de retorno

    never indica que nunca retornará um valor…
  82. / creates a function with never return type function redirect(string

    $url) : never { echo "redirected to $url . . . \n"; header('Location: ' . $url); exit(); } redirect('https: / / w w w .example.com'); / / redirected to https: / / w w w .example.com . . . 
 / / The rest of the code will not be executed! echo 'this will not be shown . . . ';
  83. o objetivo do tipo de retorno never é indicar uma

    função que previne que o resto do código chamado seja executado
  84. se uma função ou método com o tipo de retorno

    never não lançar uma exceção ou não terminar o programa será lançada a exceção TypeError
  85. / / create a function with never return type function

    dispatch(string $message) : never { echo $message; } dispatch('test'); / / Uncaught TypeError: dispatch() : never - returning / / function must not implicitly return
  86. o suporte ao tipo de retorno never torna possível não

    utilizar mais a annotation @return noreturn
  87. $ alias php81='docker container run - it - - rm

    - v `pwd`:/app - w /app php:8.1.0RC5-cli - alpine3.14 php’
  88. $ php81 - - version 
 PHP 8.1.0RC5 (cli) (built:

    Oct 28 2021 23 : 22 : 17) (NTS) Copyright (c) The PHP Group Zend Engine v4.1.0-dev, Copyright (c) Zend Technologies
  89. dependendo do editor que você utilizar, você pode ter problemas

    com o syntax highlight e o aviso de erros do editor
  90. o PHP tem tido uma enorme evolução e tem se

    tornado uma linguagem mais robusta
  91. porém, sem perder a fl exibilidade e a pequena curva

    de aprendizado que o torna uma linguagem tão democrática
  92. as novas funcionalidades ajudarão o seu código a ter mais

    garantias, ser mais expressivo e te de dar mais poderes