BT

Disseminando conhecimento e inovação em desenvolvimento de software corporativo.

Contribuir

Tópicos

Escolha a região

Início Artigos PHP 7 - Introdução e melhorias no POO

PHP 7 - Introdução e melhorias no POO

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.

Avalie esse artigo

Relevância
Estilo/Redação

Conteúdo educacional

BT