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.

PHP Básico
Curso de PHP Básico
CONHEÇA O CURSO

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:

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

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:

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

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

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.

<?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):

<?php

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

Uma documentação completa da libsodium você encontra aqui.

Dica de leitura: Checklist de segurança para autenticação

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:

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.

Teste você mesmo: https://3v4l.org/hCYKo

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".

Teste você mesmo: https://3v4l.org/HFDZk

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:

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

Teste você mesmo: https://3v4l.org/4V2Ha

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

Teste você mesmo: https://3v4l.org/IA9QJ

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:

<?php

$nome = "TreinaWeb";

echo count($nome);

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

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

Teste você mesmo: https://3v4l.org/c2LTT

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:

<?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:

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:

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.

Teste você mesmo: https://3v4l.org/J9JXR

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:

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);

Teste você mesmo: https://3v4l.org/7qhb3

PHP Intermediário
Curso de PHP Intermediário
CONHEÇA O CURSO

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.

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.

Foi um prazer ter a sua companhia e até o final de 2018, quando estaremos aqui, novamente, falando sobre a futura nova versão do PHP.

Um abraço!

PHP Avançado
Curso de PHP Avançado
CONHEÇA O CURSO
Deixe seu comentário
Share

Head de desenvolvimento. Vasta experiência em desenvolvimento Web com foco em PHP. Graduado em Sistemas de Informação. Pós-graduando em Arquitetura de Software Distribuído pela PUC Minas. Zend Certified Engineer (ZCE) e Coffee Addicted Person (CAP). @KennedyTedesco