Uma introdução prática à Reflection no PHP

Analisando ou modificando estruturas no PHP com PHP

Marcos Felipe
@omarkdev
3 min readMar 24, 2020

--

São inúmeras linguagens de programação que disponibiliza mecanismos para se fazer reflexão em estruturas de dados, no PHP isso também não seria diferente. Mas antes precisamos entender, o que é reflexão?

Em ciência da computação, reflexão computacional (ou somente reflexão) é a capacidade de um programa observar ou até mesmo modificar sua estrutura ou comportamento. — Wikipedia.

Se você tem uma pequena vivência com o PHP, provavelmente já deve ter encontrado algum código “mágico” que resolve algum problema. Um exemplo um pouco comum é a injeção de dependência do Laravel (que não é exclusividade da ferramenta), vamos ver um exemplo (caso você não tenha vivência com o Laravel, não tem problema):

Se analisarmos o exemplo, vemos que o construtor da nossa classe UserController espera uma instância de UserRepository, certo? Até aqui, sem problemas, apenas PHP. A “mágica” do Laravel acontece quando o próprio framework cria a instância de UserRepository e passa automaticamente para o nosso controller. Para isso, o framework utiliza um padrão chamado service container que por outro lado utiliza uma técnica chamada injeção de dependência. Basicamente, o service container analisa que a classe UserController precisa de um UserRepository para ser instanciado e cria essa instância, mas como ele sabe que ele precisa dessa instância? Com reflexão.

Trabalhar com reflexão no PHP é possível graças as classes mágicas de Reflection do PHP. Essas classes estão disponíveis no core da linguagem desde a versão 5, então não é necessário fazer nenhuma instalação. Existem algumas classes de Reflection no PHP, sendo que cada uma depende de onde você vai aplicar:

Vamos seguir com a ideia do exemplo em Laravel, mas agora fora do framework. Imagine que precisamos instanciar a classe UserController que espera uma instância de UserRepository, tudo isso fora do framework.

Analisando o nosso pequeno exemplo podemos ver que precisamos descobrir o que o construtor necessita para que possamos instanciar, tudo isso de forma “mágica”, utilizando reflexão. Se olharmos a lista das classes disponíveis, podemos notar que existem 2 tipos de classes que chamam a nossa atenção para esse caso, são as ReflectionParameter e ReflectionMethod, porem olhando a assinatura é possível notar que ReflectionParameter não serve diretamente para o nosso caso, pois o primeiro argumento é um callable e não é o caso do nosso __construct, então sobra o ReflectionMethod. Então, basta instanciar a classe ReflectionMethod passando o nosso controller junto com o nome do nosso método que é __construct.

Criamos a nossa reflexão do método __construct utilizando a classe ReflectionMethod. O interessante de se analisar é que o método getParameters() da classe de reflexão retorna uma lista de ReflectionParameter que representa cada parâmetro, ou seja, mesmo que não utilizando o ReflectionParameter diretamente acabamos chegando na ideia do mesmo resultado, tudo isso graças à uma ótima API das classes. Isso não é particularidade apenas da ReflectionMethod, podemos fazer o mesmo utilizando a classe ReflectionClass, criando uma reflexão para o nosso controller e analisando o construtor do alvo.

Dessa maneira, conseguimos começar do nível de cima e ir acessando às nossas necessidades até o último nível. Com esses pequenos exemplos, conseguimos começar a entender como utilizar a API de reflexão do PHP e o básico (bem básico) de como um service container funciona.

Os exemplos podem ter ficado um pouco longos mas são bem simples, pois são apenas um começo de como a reflexão do PHP funciona, de qualquer maneira aconselho você a começar a testar cada uma das classes e entender suas particularidades e funcionalidades.

Espero que isso te ajude de alguma forma.

--

--

Marcos Felipe
@omarkdev

Software Developer, Founder of CrowLabs and technology lover.