PHP 8.0 🐘
Uma nova versão, uma nova era
#php80
PHP 8.0 🐘
calendário de lançamentos (2020)
Junho 25 ~ Julho 23 - Alphas (1, 2, 3)
Agosto 4 ~ Congelamento de Funcionalidades (F.F ❄️)
Agosto 6 ~ Setembro 17 - Betas (1, 2, 3, 4)
Outubro 1 ~ Novembro 12 - Candidatos a Lançamento (1, 2, 3, 4, 5)
26 Novembro - Lançamento Geral (G.A. 🔥)
PHP 8.0 🐘
VERSÕES SUPORTADAS EM 2021
PHP 7.2 - Não será suportada
PHP 7.3 - Apenas Correções de Segurança
PHP 7.4 - Suporte Ativo
PHP 8.0 - Suporte Ativo
#php80
- Gabriel Caruso 🇧🇷 ~> 🇳🇱
- Desenvolvedor Backend @ SurveyMonkey
- Contribuidor OSS 👨🏻💻
#php80
- Melhorias de Performance
- Algumas das novas funcionalidades
- Algumas mudanças
- Quebras de Compatibilidade
- Mudanças Internas
- Por detrás das câmeras do desenvolvimento do PHP 8.0
Agenda
#php80
Melhorias de Performance 📈
JIT (Just-in-time)
- Não espere melhorias de performance como PHP 5.6 ~> PHP 7.0
- Processos Pesados irão se beneficar disto, não simples and rápidas APIs
Palestras sobre JIT
- https://youtu.be/g3RPYtwP1jk: Benoit Jacquemont (em Francês)
- https://youtu.be/JZAs1YTcRHM: Nickolas da Silva (em Português)
- https://youtu.be/5H77TnoLLcU: Nikita Popov (em Inglês)
- https://youtu.be/7UOWus-5yxg: Dmitry Stogov (em Russo)
Amanhã (05/12) - Ricardo Coelho com "JIT - E eu com isso?"
#php80
Instâncias GRAVITON2 ARM64 da AWS
- Desde o PHP 7.4, a AWS tem ajudado o PHP com código melhorando a performance
- Blog post com todas as mudanças e benchmarks
#php80
Funcionalidades 🔥
`match` Control Structure
`mixed` type
`?->` Operator
Constructor Property Promotion
`Stringable` Interface
Attributes
New `string_*` functions
Weak Maps
`static` return type
Validation for abstract trait methods
New `fdiv` function
Trailing commas in more places
DOM Living Standard APIs
New `preg_last_error_msg` function
Cryptographic Message Syntax (CMS) (RFC 5652) support
Array sorting functions are now stable
Union Types
Named Arguments
`PhpToken` class
New `get_resource_id` function
PHP 8.0 tem muitas funcionalidades
`match` Control Structure
`?->` Operator
Attributes
Union Types
Named Arguments
mas vamos focar nestas
Union types
<?php declare(strict_types=1);
class Number
{
/** @var int|float $number */
private $number;
/** @param int|float $number */
public function setNumber($number)
{
$this->number = $number;
}
/** @return int|float */
public function getNumber()
{
return $this->number;
}
}
Union types
<?php declare(strict_types=1);
class Number
{
/** @var int|float $number */
private $number;
/** @param int|float $number */
public function setNumber($number)
{
$this->number = $number;
}
/** @return int|float */
public function getNumber()
{
return $this->number;
}
}
$number = new Number();
$number->setNumber('string');
echo $number->getNumber(); // 'string'
Union types
<?php declare(strict_types=1);
class Number
{
/** @var int|float $number */
private $number;
/** @param int|float $number */
public function setNumber($number)
{
if (!is_int($number) && !is_float($number)) {
throw new \InvalidArgumentException(
sprintf('Argument $number should be either an integer or float, %s given', gettype($number))
);
}
$this->number = $number;
}
/** @return int|float */
public function getNumber()
{
return $this->number;
}
}
$number = new Number();
$number->setNumber('string'); // InvalidArgumentException: Argument $number should be either an integer or float, string given
Union types
<?php declare(strict_types=1);
class Number
{
private int|float $number;
public function setNumber(int|float $number): void
{
$this->number = $number;
}
public function getNumber(): int|float
{
return $this->number;
}
}
Union types
<?php declare(strict_types=1);
class Number
{
private int|float $number;
public function setNumber(int|float $number): void
{
$this->number = $number;
}
public function getNumber(): int|float
{
return $this->number;
}
}
$number = new Number();
$number->setNumber('string'); // Number::setNumber(): Argument #1 ($number) must be of type int|float, string given
<?php declare(strict_types=1);
class Collection
{
private array $items;
public function setItem(string $index, array|bool|callable|int|float|null|object|string $value): void
{
$this->items[$index] = $value;
}
public function getItem(string $index): array|bool|callable|int|float|null|object|string
{
return $this->items[$index];
}
}
Union types
mixed type
<?php declare(strict_types=1);
class Collection
{
private array $items;
public function setItem(string $index, mixed $value): void
{
$this->items[$index] = $value;
}
public function getItem(string $index): mixed
{
return $this->items[$index];
}
}
match
<?php declare(strict_types=1);
$value = '2';
switch ($value) {
case 0:
$result = 'Foo';
break;
case 1:
$result = 'Bar';
break;
case 2:
$result = 'Baz';
break;
}
echo $result; // 'Baz'
match
<?php declare(strict_types=1);
$value = '3';
switch ($value) {
case 0:
$result = 'Foo';
break;
case 1:
$result = 'Bar';
break;
case 2:
$result = 'Baz';
break;
}
echo $result; // Warning: Undefined variable $result
match
<?php declare(strict_types=1);
$value = '3';
switch ($value) {
case 0:
$result = 'Foo';
break;
case 1:
$result = 'Bar';
break;
case 2:
$result = 'Baz';
break;
default:
throw new \InvalidArgumentException(sprintf('No `case` for $value %s', $value));
}
echo $result; // InvalidArgumentException: No `case` for $value 3
match
<?php declare(strict_types=1);
$value = 2;
echo match ($value) {
0 => 'Foo',
1 => 'Bar',
2 => 'Baz',
}; // Baz
match
<?php declare(strict_types=1);
$value = 3;
echo match ($value) {
0 => 'Foo',
1 => 'Bar',
2 => 'Baz',
}; // UnhandledMatchError: Unhandled match value of type int
Nullsafe operator
<?php declare(strict_types=1);
$neighborhood = $address->getNeighborhood(); // returns either NULL or a Neighborhood object
$neighborhoodName = $neighborhood ? $neighborhood->getName() : null;
if ($neighborhoodName !== null) {
// do something with $neighborhoodName
}
Nullsafe operator
<?php declare(strict_types=1);
$neighborhoodName = $address->getNeighborhood()?->getName();
if ($neighborhoodName !== null) {
// do something with $neighborhoodName
}
named arguments
<?php declare(strict_types=1);
$items = [
1, 2, 'foo',
];
$integers = array_filter($items, fn (mixed $item): bool => is_int($item));
var_dump($integers); // [1, 2]
named arguments
<?php declare(strict_types=1);
var_dump(
array_fill(2, 3, 'PHP')
);
named arguments
<?php declare(strict_types=1);
var_dump(
array_fill(2, 3, 'PHP')
); // [2 => 'PHP', 3 => 'PHP', 4 => 'PHP']
named arguments
<?php declare(strict_types=1);
var_dump(
array_fill(start_key: 2, count: 3, value: 'PHP')
); // [2 => 'PHP', 3 => 'PHP', 4 => 'PHP']
named arguments
<?php declare(strict_types=1);
class Person
{
public function __construct(string $name, int $age)
{
// ...
}
}
new Person(name: 'Gabriel Caruso', age: 22);
named arguments
<?php declare(strict_types=1);
interface Person
{
public function setName(string $name);
}
class MyPerson implements Person
{
public function setName(string $fullName) {}
}
$person = (new MyPerson)->setName('Gabriel Caruso'); // fullName or name?
named arguments
<?php declare(strict_types=1);
interface Person
{
public function setName(string $name);
}
class MyPerson implements Person
{
public function setName(string $fullName) {}
}
$person = (new MyPerson)->setName(fullName: 'Gabriel Caruso'); // Named Arguments allows renaming
named arguments
<?php declare(strict_types=1);
class User
{
public function __construct(
bool $admin,
bool $active,
?array $rules = [],
) {
// Construct the object...
}
}
$user = new User(true, false, null);
named arguments
<?php declare(strict_types=1);
class User
{
public function __construct(
bool $admin,
bool $active,
?array $rules = [],
) {
// Construct the object...
}
}
$user = new User(
admin: true,
active: false,
rules: null
);
named arguments
<?php declare(strict_types=1);
function randomOrder(int $arg1, string $arg2, float $arg3) {}
randomOrder(arg2: 'PHP', arg3: 8.0, arg1: 1);
function optionals(string $arg1 = 'default', int $arg2 = 1) {}
optionals(arg2: 3);
function skipping(int $arg1, string $arg2, float $arg3) {}
skipping(1, 'PHP', arg3: 8.0); // This is allowed
skipping(1, arg2: 'PHP', 8.0); // Fatal error: Cannot use positional argument after named argument
attributes
<?php declare(strict_types=1);
/** @Entity */
final class User
{
/**
* @ORM\Id()
* @ORM\Column(type="integer")
*/
private int $id;
/** @ORM\Column() */
private string $name;
}
Annotations
Elas são usadas para documentar o seu código
attributes
Atributos mudam o comportamento do seu código. Pense em "meta programação"
attributes
<?php declare(strict_types=1);
#[Entity]
final class User
{
#[ORM\Id()]
#[ORM\Column(type="integer")]
private int $id;
#[ORM\Column()]
private string $name;
}
vantagens de ter attributes nativos no php
- Muitas bibliotecas, projetos e framework tem suas próprias implementações. Isso será centralizado agora
- Caching, otimizações e tudo do bom e do melhor que o PHP tem a oferecer
- Annotations serão usadas para documentação
um ponto super importante sobre o ATTRIBUTES no php 8.0 ⚠️
- Não converta Annotations para Attributes antes de checar se a library, ou framework, tem suporte a eles
- Dê uma lida na RFC, na parte de "Reflection" para entender como adicionar support à Attributes
mudanças 🔩
throw agora é uma expressão
<?php declare(strict_types=1);
$callable = fn() => throw new Exception(); // this was not possible before PHP 8.0
$value = $nullableValue ?? throw new InvalidArgumentException(); // `throw` is now considered an expression
VARIÁVEL no catch não é mais obrigatória
<?php declare(strict_types=1);
try {
$this->login($user);
} catch (PermissionException) { // $exception variable is no longer required
throw AuthenticationException::failedLogin();
}
constante mágica ::class agora supporta objetos
<?php declare(strict_types=1);
namespace Foo\Bar {
class Baz {}
$baz = new \Foo\Bar\Baz();
var_dump(
$baz::class, // "Foo\Bar\Baz"
);
}
<?php declare(strict_types=1);
namespace Foo\Bar {
class Baz {}
$baz = new \Foo\Bar\Baz();
var_dump(
$baz::class, // "Foo\Bar\Baz"
get_class($baz) // "Foo\Bar\Baz"
);
}
constante mágica ::class agora supporta objetos
erros em PDO agora são PDO::ERRMODE_EXCEPTION
- Era `PDO::ERRMODE_SILENT`, e agora é `PDO::ERRMODE_EXCEPTION`
- Problemas comuns como consultas `SQL` com errors de sintaxe serão expostos pela extensão
#php80
ARGUMENTOS OPCIONAIS SEGUIDOS DE REQUERIDOS ESTÁ DEPRECATED
#phpcs2020
<?php declare(strict_types=1);
function test(string $param = '', $param2) {
// do something with $param and $param2
}
// Deprecated: Required parameter $param2 follows optional parameter $param
Quebras de Compatibilidade 🚨
REMOÇÃO DAS FUNCIONALIDADES DO 7.x QUE ESTAVAM deprecated
- Declaração de constantes não case-sensitive
- Construtores PHP 4
- Chamadas estáticas à métodos não estáticos
- Alias para algumas funções MBString
- Cast `(unset)`
- Dê uma lida no PR para a lista completa...
MÉTODOS MÁGICAS TERÃO SUAS ASSINATURAS CHECADAS
<?php declare(strict_types=1);
class Foo
{
public function __toString(): bool
{
return true;
}
}
// Declaration of Foo::__toString(): bool must be compatible with Stringable::__toString(): string
checagens mais estritas para operações aritméticas/bitwise
<?php declare(strict_types=1);
$result = [] % [42]; // It will throw a "TypeError: Unsupported operand types"
$array = [2, 3];
$array++; // It will throw a "TypeError: Cannot increment array"
$object = new stdClass();
$object++; // It will throw a "TypeError: Cannot increment stdClass"
COMPARAÇÕES QUE FAZEM SENTIDO ENTRE STRINGS E NÚMEROS
<?php declare(strict_types=1);
var_dump(
0 == "0", // continua `true`
0 == "0.0", // continua `true`
0 == "foo", // era `true`, agora é `false`
0 == "", // era `true`, agora é `false`
42 == " 42", // continua `true`
42 == "42foo", // era `true`, agora é `false`
);
Mudanças Internas 👀
melhorias para a API de REFLECTION
<?php declare(strict_types=1);
$reflectionFunction = new ReflectionFunction('array_filter');
foreach ($reflectionFunction->getParameters() as $parameter) {
echo sprintf('Parameter $%s, type %s', $parameter->getName(), $parameter->getType() ?? '*NO TYPE DEFINED*') . PHP_EOL;
}
echo 'array_filter return type: ' . $reflectionFunction->getReturnType() ?? '*NO TYPE DEFINED*';
#php80
<?php declare(strict_types=1);
$reflectionFunction = new ReflectionFunction('array_filter');
foreach ($reflectionFunction->getParameters() as $parameter) {
echo sprintf('Parameter $%s, type %s', $parameter->getName(), $parameter->getType() ?? '*NO TYPE DEFINED*') . PHP_EOL;
}
echo 'array_filter return type: ' . $reflectionFunction->getReturnType() ?? '*NO TYPE DEFINED*';
// Before PHP 8.0
// Parameter $arg, type *NO TYPE DEFINED*
// Parameter $callback, type *NO TYPE DEFINED*
// Parameter $use_keys, type *NO TYPE DEFINED*
// array_filter return type: *NO TYPE DEFINED*
melhorias para a API de REFLECTION
#php80
<?php declare(strict_types=1);
$reflectionFunction = new ReflectionFunction('array_filter');
foreach ($reflectionFunction->getParameters() as $parameter) {
echo sprintf('Parameter $%s, type %s', $parameter->getName(), $parameter->getType() ?? '*NO TYPE DEFINED*') . PHP_EOL;
}
echo 'array_filter return type: ' . $reflectionFunction->getReturnType() ?? '*NO TYPE DEFINED*';
// After PHP 8.0
// Parameter $array, type array
// Parameter $callback, type ?callable
// Parameter $use_keys, type int
// array_filter return type: array
melhorias para a API de REFLECTION
#php80
QUAIS PROJETOS IRÃO SE BENEFICAR DESSAS MELHORIAS?
-
phpstan/phpstan
-
vimeo/psalm
-
roave/better-reflection
-
jetbrains/phpstorm-stubs
#php80
mudanças a alguns PHP INI
- Padrão do `error_reporting` agora é `E_ALL`. Anteriormente não incluia `E_NOTICE` e `E_DEPRECATED`
- `zend.exception_string_param_max_len` agora é configurável, melhorando `Throwable::getTraceAsString()`
- `assert.exception` agora é `true`, lançando uma exceção ao invés de um Warning
#php80
Por detrás das câmeras do desenvolvimento do PHP 8.0 🎥
quem está por trás do php 8.0?
gerentes da versão
Gabriel Caruso (sua primeira vez)
Sara Golemon (gerente do PHP 7.2)
#php80
- Responsáveis por tomarem conta e coordernar todos os lançamentos desde o Alpha 1 até G.A
- Responsáveis por versões patch a cada 4 semanas após G.A.
- (Não oficial, mas) Os gerentes são aqueles que vão à eventos, meetups, escrevem blog posts sobre a nova versão para espalhar as novidades na comunidade
gerentes da versão
contribuidores
Dmitry Stogov (JIT)
Nikita Popov (JetBrains)
#php80
Christoph M. Becker (Microsoft)
contribuidores
#php80
Matteo Beccati (PDO/Postgres)
contribuidores
#php80
novos contribuidores
#php80
novos contribuidores
#php80
Benjamin Eberlei (Doctrine)
contribuidores famosos
#php80
PHP 8.0 EM ALGUMAS PALAVRAS?
FOI UMA VERSÃO EM QUE A COMUNIDADE AJUDOU BASTANTE A DESENVOLVER
será fácil migrar para o php 8.0 vindo de verSões php 7.x?
sim, e se você usa uma ferramenta de análise estática no seu código, será ainda mais fácil
QUER ajudar o php 8.0?
Teste, e reporte bugs no https://bugs.php.net
COMPARTILHE: HTTPS://PHP.NET/RELEASES/8.0
ESSA PALESTRA FOI SÓ A PONTA DO ICEBERG 🗻
VOCÊ PODE CONFERIR TODAS AS REFERÊNCIAS PARA ESSA PALESTRA, COM blog posts, VÍDEOS NO youtube E MUITO MAIS.
Muito Obrigado ♥️
Por favor, deixe feedback para está palestra 👉🏻
Perguntas? 🤔
PHP 8.0: Uma nova versão, uma nova era
By Gabriel Caruso (Caruso)
PHP 8.0: Uma nova versão, uma nova era
PHP 8.0 está chegando e você deve estar se perguntando: quais são as novas funcionalidades? Será que eles corrigiram aqueles bugs estranhos? Será que a minha aplicação ficará mais rápida? Consigo dar suporte ao PHP 7 e ao PHP 8 ao mesmo tempo na minha biblioteca ou framework? Nesta palestra, vamos passar um tempo vendo o que há de novo no PHP 8.0, o que mudou internamente e externamente na linguagem, tanto novas funcionalidades quanto mudanças de comportamento. Como um dos Release Managers, Gabriel Caruso irá te contar tudo sobre, dando todos os recursos necessários para você se atualizar sobre essa nova versão major do PHP, programada para ser lançada em Novembro de 2020.
- 1,949