PHP

Novidades do PHP 7.2

Novidades do PHP 7.2 - No final do ano passado eu escrevi sobre as novidades do php 7.1. Quase um ano depois, é hora de voltar à tona o assunto, mas dessa vez sobre a próxima minor version, a 7.2.

Novidades do PHP 7.2 – No final do ano passado eu escrevi sobre as novidades do php 7.1. Quase um ano depois, é hora de voltar à tona o assunto, mas dessa vez sobre a próxima minor version, a 7.2.

Se você ainda não teve a oportunidade de ler, eu também escrevi sobre a força do PHP e do seu ecosistema e, nesse artigo, eu desconstruo alguns mitos e preconceitos que ainda permeiam a linguagem.

Quando o PHP 7.2 estará disponível para uso em produção?

O cronograma é de que tenhamos a versão final do PHP 7.2 no dia 30 de novembro (Daqui um mês e alguns dias).

Atualmente estamos na Release Candidate 5 (RC5). O caminho a ser percorrido até o lançamento:

DateRelease
Oct 26 2017RC 5
Nov 7 2017PHP 7.2.0 branched
Nov 9 2017RC 6
Nov 30 2017GA

O que posso esperar do PHP 7.2?

Essa não será uma versão com uma grande variedade de inclusões e novas features. O foco ficou em melhorar a estabilidade e consistência e também em descontinuar algumas coisas que há tempo estavam no radar da “exclusão”.

Melhorias no core continuam sendo aplicadas e a linguagem segue um rumo para ficar cada vez mais rápida, como pode ser visto nesse estudo:

Gráfico teste performance

No teste realizado pelo Sebastian Bergmann (criador do PHPUnit) o PHP 7.2 também foi bem:

Gráfico teste pelo sebastian bergmann

O principal destaque, no entanto, refere-se à inclusão da libsodium na standard library do PHP.

#PHP 7.2 will be the first programming language to accept modern cryptography into its standard library.https://t.co/mNDK9zxcw5— Scott Arciszewski (@CiPHPerCoder) February 10, 2017

A libsodium é uma completa toolkit de segurança. Moderna, com boa auditoria e recomendada por grandes nomes da comunidade de especialistas em segurança.

Entre todas as features da libsodium, talvez a que mais toca a grande maioria dos desenvolvedores PHP, refere-se ao algoritmo de hashing de passwords, o Argon2i.

Desde a implementação da API de hashing de password no PHP 5.5 a adoção foi grande, principalmente por parte dos frameworks. No entanto, o algoritmo padrão utilizado por ela é o bcrypt.Copiar

<?php

$hash = password_hash('4&4*Q?_2c*rFPW+jj^KAxnBQ9+Q5X@ep');

Nesse exemplo, o password 4&4*Q?_2c*rFPW+jj^KAxnBQ9+Q5X@ep será transformado usando o algoritmo bcrypt.

Agora, no PHP 7.2, será possível informar o Argon2i como algoritmo de hashing (no segundo parâmetro da função):Copiar

<?php

$hash = password_hash('4&4*Q?_2c*rFPW+jj^KAxnBQ9+Q5X@ep', PASSWORD_ARGON2I);

Melhorias de consistência

A lista completa das alterações do PHP 7.2 pode ser encontrada no hotsite de RFC’s. Sugiro que você olhe cada uma.

Vou destacar abaixo as que eu considero de maior importância / relevância.

Sobrescrita de métodos abstratos

Esse código nas versões anteriores ao PHP 7.2 gera um erro fatal:

<?php

abstract class A
{ 
    abstract public function bar(\stdClass $x);
}

abstract class B extends A
{
    abstract public function bar($x) : \stdClass; 
}

O erro que é gerado:Copiar

Fatal error: Can't inherit abstract function A::bar() (previously declared abstract in B)

Até então não era possível sobrescrever métodos abstratos. No PHP 7.2 tornou-se possível.

Previnir que number_format() retorne zero negativo

Essa é mais uma daquelas alterações para dar mais consistência pra linguagem.

Por exemplo, o código abaixo retorna uma string "-0":

<?php

echo number_format(-0.01); // "-0" (PHP <= 7.1)

No PHP 7.2 passa a retornar "0".

Conversão de chaves numéricas no casting de arrays/objetos

Um problema que ocorre nas versões anteriores à 7.2:

<?php

$arr = [
    0 => 1,
    1 => 2, 
    2 => 3,
]; 

$obj = (object) $arr;

var_dump($obj);

Nessas versões, o retorno é:

object(stdClass)#1 (3) {
  [0]=> int(1)
  [1]=> int(2)
  [2]=> int(3)
}

Veja que é um retorno discrepante. O casting do array para objeto faz com que os índices numéricos se percam.

No PHP 7.2 o retorno será o esperado:Copiar

object(stdClass)#1 (3) {
  ["0"]=> int(1)
  ["1"]=> int(2)
  ["2"]=> int(3)
}

Outras variantes do mesmo problema você encontra na RFC dessa alteração.

Emitir warning se um valor null for passado para get_class()

Um valor nulo pode levar a get_class() a produzir resultados inesperados.

Por exemplo:

<?php

class MyRepo
{
    public function find($id)
    {
        return null;
    }
}

class Foo
{
    function bar($repository)
    {
        $result = $repository->find(100);
 
        echo get_class($result);
    }
}

$foo = new Foo();
$foo->bar(new MyRepo);

Espera-se que a função bar() imprima o nome da classe do objeto contido em $result. Entretanto, $result sendo nulo, é retornado o nome da classe do objeto no contexto em que get_class() foi chamada. O exemplo acima retorna Foo nas versões inferiores ao PHP 7.2

No PHP 7.2 esse exemplo retorna um warning:

Warning: get_class() expects parameter 1 to be object, null given

Contar apenas coisas contáveis

Chamar a função count() em valores escalares ou objetos que não implementem a interface Countable resulta em 1. O que é um resultado não lógico e é preciso ter cuidado com o que se faz com ele.

Um exemplo:Copiar

<?php

$nome = "cafecodificado";

echo count($nome);

No PHP 7.2 o retorno também é 1, no entanto, um warning é gerado:Copiar

Warning: count(): Parameter must be an array or an object that implements Countable

Parameter Type Widening

Nas versões inferiores ao PHP 7.2 os parâmetros de um método estendido precisam ser compatíveis com os da classe pai. Eles precisam ser fiéis à assinatura (consequentemente também aos tipos explicitamente solicitados).

Por exemplo:Copiar

<?php

class ArrayClass
{
    public function foo(array $foo)
    {
        // TODO
    }
}

class EverythingClass extends ArrayClass
{
    public function foo($foo)
    {
        // TODO
    }
}

O método foo() da classe EverythingClass nas versões anteriores gera um warning:Copiar

Warning: Declaration of EverythingClass::foo($foo) should be compatible with ArrayClass::foo(array $foo)

Ele pede que seja declarado de acordo com a classe pai:Copiar

class EverythingClass extends ArrayClass
{
    public function foo(array $foo)
    {
        // TODO
    }
}

No PHP 7.2 esse warning não mais existe. Fica flexível para quem estende se vai exigir aquele tipo declarado no parâmetro ou não. Isso favorece a aplicação de contravariância e covariância.

Melhoria no suporte ao uso de vírgulas

Um padrão de estilo de código muito usado em PHP é usar uma vírgula no último item de um array, assim:

$array = [
    'foo',
    'bar',
];

Muitos desenvolvedores são a favor da extensão desse suporte (da vírgula) para outros contextos, mas existe uma certa resistência.

O que conseguiram na versão 7.2 foi trazer isso para a instrução use:Copiar

use Test {
    Foo,
    Bar,
	Baz,
};

$foo = new Foo();
$bar = new Bar();
$baz = new Baz();

Nas versões anteriores ao PHP 7.2 essa vírgula na class “Baz” gera um erro fatal.

Object Type Hinting

Essa foi uma adição muito aguardada por aqueles que passaram a usar Scalar Type Declarations, adicionado na versão 7 do PHP.

Que basicamente é uma forma do desenvolvedor conseguir exigir um tipo escalar no parâmetro de uma função e de também informar qual será o tipo do retorno dela.

No PHP 7.2 adicionaram o tipo genérico object. Quando utilizado no parâmetro de um método ou função, indica que um objeto deve ser passado. Não importa de que tipo. Precisa ser um objeto.

Exemplo:

<?php

class Foo 
{
    // TODO
}

function bar(object $object) {
    // TODO
}

bar(new Foo);

Descontinuações

Os seguintes recursos foram descontinuados:

  • __autoload (prefira usar spl_autoload_register)
  • $php_errormsg (prefira usar error_get_last())
  • create_function()
  • mbstring.func_overload
  • (unset) cast
  • parse_str() sem um segundo argumento
  • gmp_random()(prefira usar gmp_random_bits() e gmp_random_rage())
  • each()
  • assert() com uma string no argumento
  • O argumento $errcontext de set_error_handler() foi descontinuado.

A descrição e a proposta pra cada uma desses itens você pode ver na https://wiki.php.net/rfc/deprecations_php_7_2 que foi criada pra esse objetivo.

Concluindo

O PHP 7 segue sua jornada, enquanto o suporte ao PHP5 está próximo de ser encerrado por completo.

Calendário de suporte de versões

Ainda não migrou o seu projeto para PHP 7? Essa é a hora. Todos os frameworks modernos já o suportam com maestria em suas últimas versões.