Pontos Principais
-
O PHP 7 foi a versão mais aguardada do PHP após o PHP 5. O PHP 7.4 é a segunda versão final do PHP 7;
-
Além de fornecer recursos novos, o PHP 7.x é mais rápido e pronto para a nuvem;
-
O PHP 7.2 adicionou suporte parcial para Contra-Variância e Covariância, e o PHP 7.4 adicionou suporte completo para este recurso;
-
O PHP 7.2 adicionou um novo tipo chamado
object
; -
O PHP continua sendo uma das linguagens mais usadas na web. O PHP é usado por 78,6% dos sites cuja linguagem de programação do servidor é conhecida.
O PHP quase se tornou uma linguagem esquecida, com mais de uma década sem uma nova versão principal após o PHP 5.0 em 2004. Para piorar as coisas, o PHP 6.x foi abandonado por causa de uma adição planejada de suporte nativo ao Unicode no PHP que poderia não ser implementado.
O PHP 7.0 é uma versão principal com várias melhorias e novos recursos adicionados. Alguns desses recursos destacados no 7.0 são declarações do tipo escalar para strings, números inteiros, números de ponto flutuante e booleanos, declarações de tipo nos retornos das funções, uma nova função chamada define()
para arrays constantes e a adição das classes anônimas. Alguns recursos foram adicionados para melhorar o suporte ao unicode, incluindo a classe IntlChar
e a sintaxe de escape do ponto de código do unicode.
Além disso, foram adicionadas expectativas para aprimorar a função assert()
, enquanto as funções de retorno e delegação do gerador melhoram a funcionalidade do mesmo. Versões secundárias, incluindo o PHP 7.1 ao 7.4, adicionaram outros recursos.
Nesta série de artigos, discutiremos os novos recursos presentes nas versões do PHP 7.x. Mas primeiro, vamos discutir por que utilizar o PHP 7.
Por que usar o PHP 7?
Em resumo, o PHP 7 eleva o PHP ao nível das outras linguagens mais modernas.
Algumas das principais razões para usar o PHP 7 são as seguintes:
1. O WordPress é usado por 36,4% de todos os sites da internet. O PHP 7 é a versão oficial recomendada para o WordPress.
"Ao atualizar para uma nova versão do PHP, o WordPress incentiva a atualização para a versão recomendada do PHP, o 7.3. A equipe interna do PHP fez um ótimo trabalho, tornando esta a versão mais veloz do PHP. Isso significa que a atualização melhorará a velocidade dos sites, tanto para nós como para os usuários".
2. O PHP 7 oferece muitos recursos novos, como mencionado anteriormente.
3. O PHP 7 é baseado em um novo Zend Engine que dá maior desempenho e aumenta a velocidade. O Zend é muito rápido, como mostrado em vários testes de benchmark de velocidade executados em diferentes plataformas e configurações.
4. O PHP 7 usa estruturas de dados eficientes, tornando-o mais enxuto em comparação com as versões anteriores.
5. O PHP 7 está pronto para a nuvem, com a maioria dos principais provedores de serviços em nuvem dando suporte a stack do LAMP.
Configurando o ambiente
Para poder testar ou executar os scripts de amostra apresentados neste artigo, faça o download e instale a versão mais recente do PHP 7 (a PHP 7.4). Os binários para fazer o download e as etapas para instalá-los variam com a plataforma utilizada, por isso, consulte os documentos oficiais do PHP para obter maior orientação. Não se esqueça de adicionar o diretório raiz da instalação, por exemplo, C:\PHP7.4\php-7.4-ts-windows-vc15-x64-r6c9821a, ao ambiente PATH
. Renomeie o php.ini-production ou php.ini-development para php.ini. Para usar as extensões no diretório /ext, defina a diretiva extension_dir
no php.ini, como mostrado abaixo:
extension_dir = "./ext"
Inicie o servidor com o seguinte comando:
php -S localhost:8000
Adicione todos os scripts a serem executados no subdiretório de scripts no diretório raiz, que é o diretório de instalação, por exemplo, C:\PHP7\php-7.3.0-Win32-VC15-x64. O diretório raiz pode ser definido com um valor diferente usando a diretiva doc_root
no php.ini. Para tornar os scripts PHP que iremos mostrar reutilizáveis, salve-os separadamente, ao invés de testar ou executar todos os scripts como test.php.
Covariância e Contravariância
O PHP 7.2 introduziu covariância e contravariância limitadas. Covariância refere-se ao método de uma subclasse para poder retornar um tipo de retorno mais específico. Contravariância refere-se ao método de uma subclasse para aceitar um tipo de parâmetro menos específico. Mais ou menos específico, é definido no contexto de super e subclasse, com uma subclasse sendo mais específica. Uma classe que estende outra pode substituir os métodos enquanto ainda mantém a contravariância (para tipos de parâmetros) e covariância (para tipo de retorno).
O suporte à covariância e contravariância é limitado no PHP 7.2, o que implica que apenas a variação para sem nenhum tipo é suportada. Para elaborar mais essa ideia, imaginemos um tipo de retorno que pode ser definido em uma função de substituição que não existia na superclasse e um tipo de parâmetro que pode ser omitido ao substituir uma função em um parâmetro que existia na superclasse.
Vamos fazer um exemplo criando um script e declarando uma classe A
com uma única função, fn1
. Depois, vamos criar outra classe, chamada de B
que estenda a classe A
e substitua a função fn1
.
O tipo de parâmetro na função substituída fn1
é omitido, cujo padrão é misto, um tipo de parâmetro ampliado do tipo B
na classe A
. A possibilidade de omitir o(s) tipo(s) de parâmetro nos métodos substituídos, sendo abstrato ou não, é outro recurso novo no PHP 7.
O tipo de retorno na função substituída fn1
é A
, que é uma limitação do tipo misto na classe A
. Abaixo, podemos ver o script:
<?php
class A {
function fn1(B $b) {}
}
class B extends A {
function fn1($b): A{}
}
Novo tipo: Object
O PHP 7.2 adicionou suporte para um novo tipo chamado object
que pode ser usado como um tipo de parâmetro e de retorno. Instâncias de todos os tipos de classe são objetos. Para demonstrar o uso de um object
como um tipo de parâmetro e de retorno, crie um script object.php
em um diretório chamado scripts na raiz do documento e declare duas classes, ClassA
e classB
, com cada uma definindo uma função hello()
que ecoa uma string. Em seguida, adicione uma função hello()
ao próprio script com o tipo de parâmetro e de retorno como sendo object
. A função hello()
adicionada diretamente no script retorna uma instância da classe ClassB
como mostrado abaixo:
function hello(object $obj) : object
{
return new ClassB();
}
Chame a função com uma instância de ClassA
como argumento e depois chame a função hello()
no objeto retornado.
hello(new ClassA())->hello();
O object.php completo está descrito abaixo:
<?php
Class ClassA{
function hello()
{
echo "Hello from ClassA";
}}
class ClassB{
function hello()
{
echo "Hello from ClassB";
}}
function hello(object $obj) : object
{
return new ClassB();
}
hello(new ClassA())->hello();
?>
Executando o script acessando a URL http://localhost:8000/scripts/object.php irá produzir:
Hello from ClassB
Como este é o primeiro exemplo de script que executamos, o retorno no navegador é mostrado na Figura 1.
Figura 1. Retorno do object.php
O próprio tipo object
não representa uma classe, apenas representa um tipo. Uma nova instância da classe interna stdClass
será criada se qualquer tipo diferente de objeto for convertido em object
.
Um array pode ser convertido em um object
convertendo-o no tipo objeto, com o objeto resultante tendo propriedades nomeadas como as chaves do array. Para demonstrar como converter o array em um objeto e várias tarefas úteis relacionadas, vamos criar um script object_array.php e declarar um objeto convertendo-o em object
.
$obj = (object) array('journal' => 'Oracle Magazine', 'publisher' => 'Oracle Publishing','edition' => 'January February 2018');
Agora, podemos gerar as propriedades do objeto usando as chaves nomeadas.
echo $obj->{'journal'};
echo $obj->{'publisher'};
echo $obj->{'edition'};
A função bool isset(mixed $var [, mixed $...])
pode ser usada para descobrir se uma propriedade está definida, como mostrado abaixo:
var_dump(isset($obj->{'journal'}));
O retorno de uma chave de objeto usando a função de mixed key(array $array)
.
var_dump(key($obj));
Avance o ponteiro interno do array com o mixed next(array /$array)
.
next($obj);
Chame as funções isset
e key
para o próximo elemento do array. Repita a sequência de chamar as funções next
, isset
e key
para o próximo elemento. As variáveis de membro do objeto podem ser acessadas para gerar seus valores.
echo $obj->journal;
echo $obj->publisher;
echo $obj->edition;
Descubra se o objeto convertido da matriz é uma instância de stdClass
.
if($obj instanceof stdClass){
echo '$obj is instance of built-in class stdClass';
}
Uma string pode ser convertida em objeto. O valor do objeto convertido é acessado usando a variável de membro escalar. Descubra se o objeto convertido é uma instância de stdClass
.
$obj = (object) 'hello';
echo $obj->scalar;
if($obj instanceof stdClass){
echo '$obj is instance of built-in class stdClass';
}
O script object_array.php completo pode ser visto abaixo.
<?php
$obj = (object) array('journal' => 'Oracle Magazine', 'publisher' => 'Oracle Publishing','edition' => 'January February 2018');
echo $obj->{'journal'};
echo "<br/>";
echo $obj->{'publisher'};
echo "<br/>";
echo $obj->{'edition'};
echo "<br/>";
var_dump(isset($obj->{'journal'}));
echo "<br/>";
var_dump(key($obj));
next($obj);
echo "<br/>";
var_dump(isset($obj->{'publisher'}));
echo "<br/>";
var_dump(key($obj));
next($obj);
echo "<br/>";
var_dump(isset($obj->{'edition'}));
echo "<br/>";
var_dump(key($obj));
echo "<br/>";
echo $obj->journal;
echo "<br/>";
echo $obj->publisher;
echo "<br/>";
echo $obj->edition;
echo "<br/>";
if($obj instanceof stdClass){
echo '$obj is instance of built-in class stdClass';
echo "<br/>";
}
$obj = (object) 'hello';
echo $obj->scalar;
echo "<br/>";
if($obj instanceof stdClass){
echo '$obj is instance of built-in class stdClass';
}
?>
A execução do script irá produzir:
Oracle Magazine
Oracle Publishing
January February 2018
bool(true)
string(7) "journal"
bool(true)
string(9) "publisher"
bool(true)
string(7) "edition"
Oracle Magazine
Oracle Publishing
January February 2018
$obj is instance of built-in class stdClass
hello
$obj is instance of built-in class stdClass
Podemos converter não apenas arrays e strings em objetos, mas valores de qualquer tipo, incluindo int
, float
e bool
. Vamos fazer um exemplo convertendo um int
em um object
, produzindo o valor escalar e descobrindo se o objeto convertido é uma instância de stdClass
com o seguinte script:
<?php
$obj = (object) 1;
echo $obj->scalar;
echo "<br/>";
if($obj instanceof stdClass){
echo '$obj is instance of built-in class StdClass';
}?>
O resultado é o seguinte:
1
$obj is instance of built-in class stdClass
Instâncias de classes são objetos e não instâncias de stdClass
, e convertê-las em objeto não as torna uma instância de stdClass
. Para demonstrar isso, vamos criar um script chamado object_instance_of.php, declarar uma classe e instancia-la. O script abaixo mostra como descobrir se uma instância de classe é uma instância de stdClass
. O script converterá a instância da classe em um objeto e descobrirá se ele é uma instância do stdClass
. O script object_instance_of.php está escrito à seguir:
<?php
Class A{}
$A = new A;
echo '<br/>';
if ($A instanceof stdClass) {
echo '$A is instance of built-in class stdClass'; }
else{
echo '$A is not instance of built-in class stdClass';
}
echo '<br/>';
echo '<br/>';
$AObj = (object)$A;
if ($AObj instanceof stdClass) {
echo '$AObj is instance of built-in class stdClass';
}else{ echo '$AObj is not instance of built-in class stdClass';
}
echo '<br/>';
?>
</pre>
A execução do script produzirá:
<pre>
$A is not instance of built-in class stdClass
$AObj is not instance of built-in class stdClass
A execução do script produzirá:
$A is not instance of built-in class stdClass
$AObj is not instance of built-in class stdClass
Uma instância de uma classe nomeada ou anônima já é um object
e a conversão para object
não altera seu tipo. Um array vazio e o valor NULL
também podem ser convertidos em um object
. Como mencionado, o stdClass
é o objeto PHP padrão e uma instância do stdClass
é criada quando números, arrays e NULL
são convertidos em object
. Um object
de uma classe anônima, um object
criado a partir de um array vazio, um objeto criado a partir de um NULL
ou de uma classe sem funções ou variáveis não são considerados vazios e a função empty()
não retorna TRUE
quando aplicados a qualquer um deles. A função empty()
retorna TRUE
somente se uma variável ou objeto não existir ou for FALSE
.
Para testar tudo isso, vamos criar um script object_empty.php e copiar o seguinte código abaixo:
<?php
$obj1 = (object)(new class{}); // Instanciando uma classe anônima
$obj2 = (object)[]; // Convertendo um array vazio em object
class A{}
$A=new A(); // Instanciando uma classe vazia
var_dump($A);
echo "<br/>";
var_dump($obj1);
echo "<br/>";
var_dump($obj2);
echo "<br/>";
echo empty ($obj1);
echo "<br/>";
$obj1=NULL;
$obj3=(object)$obj1;// Convertendo um NULL em object
var_dump($obj3);
echo "<br/>";
echo empty ($A);
echo "<br/>";
echo empty ($obj2);
echo "<br/>";
echo empty ($obj3);
?>
O script cria um tipo de cada objeto de classe anônima: Um objeto criado a partir de uma matriz vazia, um objeto criado a partir de um NULL
e, um objeto de classe sem funções ou variáveis. A execução do script gerará o seguinte retorno:
object(A)#3 (0) { }
object(class@anonymous)#1 (0) { }
object(stdClass)#2 (0) { };
object(stdClass)#1 (0) { }
O tipo object
pode ser usado para contravariância (ampliação) do tipo de parâmetro e covariância (restrição) do tipo de retorno.
<?php
class A{
public function fn(object $obj) {
}
}
class B extends A{
public function fn($obj) : object {
}
}
Covariância total e contravariância
Já discutimos o suporte ao PHP 7.2 para covariância limitada, o que permite adicionar um tipo de retorno a um método em uma classe estendida, embora não haja declaração na superclasse. Também discutimos o suporte à contravariância limitada, o que permite deixar o tipo de parâmetro de método não especificado em uma classe estendida.
O PHP 7.4 adiciona suporte completo à covariância e contravariância. O suporte total permite tipos de parâmetros menos específicos e tipos de retorno mais específicos, o que implica que um tipo do parâmetro pode ser substituído por um de seus supertipos e um tipo de retorno pode ser substituído por um subtipo. Lembre-se de que o suporte à covariância e contravariância no PHP 7.2 foi limitado a uma ausência de tipo. No script a seguir, ClassB
estende ClassA
e ClassD
estende ClassC
. A função fn1
na ClassD
declara um tipo de parâmetro menos específico e um tipo de retorno mais específico do que na ClassC
.
<?php
class ClassA {}
class ClassB extends ClassA {}
class ClassC {
public function fn1(ClassB $b): ClassA {}
}
class ClassD extends ClassC {
public function fn1(ClassA $a): ClassB {}
}
?>
Algumas das características do suporte total à variância são:
- A variância total é suportada apenas se o carregamento automático for usado;
- A variância tem suporte para o tipo
object
; - A variância não tem suporte para o tipo
callable
; - Parâmetros por referência ainda são contravariantes e o tipo de retorno por referência ainda é covariante;
- A verificação de variância é feita somente após a última declaração de tipo consecutiva.
No próximo artigo desta série, discutiremos os novos recursos do PHP 7.x para classes e interfaces.
Sobre o autor
Deepak Vohra é um programador Java com as certificações Sun Certified Java Programmer and Sun Certified Web Component Developer. Deepak publicou artigos técnicos relacionados a Java e Java EE no WebLogic Developer's Journal, XML Journal, ONJava, java.net, IBM developerWorks, Java Developer's Journal, Oracle Magazine e devx. Além disso, publicou cinco livros no Docker e é um dos mentores desta tecnologia. Deepak também publicou vários artigos sobre PHP e um livro sobre Ruby on Rails para desenvolvedores de PHP e Java.