PHP - Funções anônimas estáticas


Olhando um repositório no Github (uma dia antes da criação desse post) me achamou a atenção o uso da palavra reservada static em uma função anônima, pois eu nunca tinha visto isso e, portanto, não sabia que existia essa possibilidade no PHP. Depois de estudar resolvi escrever sobre isso.

A finalidade

Fui pesquisar e entendi o porquê do uso de uma função anônima assim. Basicamente, ao declarar a função estática a variável $this não existirá no escopo da função, ou seja, a função não irá referenciar um contexto de onde ela foi declarada. Segue o exemplo em código:

<?php

class Contexto
{
    
    public function exemplo(){
        
        $funcaoSemContexto = static function(){

            // Essa variável é indefinida no escopo dessa função.
            var_dump($this);
        
        };
        
        $funcaoSemContexto();
        
    }
    
}

Sem usar a palavra reservada static, a variável $this iria apontar para uma instância da classe Contexto, já que foi nessa classe que a função anônima foi criada e, consequentemente, ela seria o contexto dessa função. Como a função foi declara estática, o seguinte erro aparece:

Fatal error: Uncaught Error: Using $this when not in object context

Troca de contexto

Vale lembrar que uma função anônima no PHP é uma instância da classe (interna do PHP) Closure e essa classe tem métodos como o método bindTo, que é responsável por adicionar um novo contexto (aka a variável $this) em uma função anônima.

Só que trocar de contexto não é possível em uma função declarada como estática, já que ela impossibilita ter contexto. Em outras palavras, não dá para usar o método bindTo em função anônima quando ela é estática.

Segue isso exemplificado mantendo o exemplo de código criado:


<?php

class Contexto
{ 

    public function exemplo(){
        
        $funcaoSemContexto = static function(){

            // Essa variável é indefinida no escopo dessa função.
            var_dump($this);
        
        };
        
        $novoContexto = new stdClass;
        $novoContexto->texto = 'Esse objeto é o novo contexto.';

        // Isso não é possível porque a função foi criada estática
        $funcaoSemContexto = $funcaoSemContexto->bindTo($novoContexto);
        $funcaoSemContexto();
        
    }
    
}

Ao executar o código acima, o erro a seguir aparece por conta da função anônima ser estática.

Warning: Cannot bind an instance to a static closure

Finalizando

Esse comportamento alcançado através funções anônimas estáticas é semelhante ao de classes estáticas, já que elas não tem contexto por não serem uma instância de um objeto. Declarar uma função anônima como estática dá essa mesma natureza (de não ter contexto) para a função.

Esse comportamento pode ser útil se por algum motivo é necessário evitar que o $this possa ser usado em uma função anônima.

Atualização

Atualizei um projeto que fiz com Slim Framework para usar as funções estáticas nos arquivos de configuração que isolam o escopo do código, pois nessas funções não existe sentido em usar o $this.


ver todos os posts
Publicado em 25/05/2020