PHP – Método BindTo() usado para clonar instâncias closure

php_code_1

Nível avançado

 

Apenas para se alinhar sobre o que está lendo: Closures são conhecidos no PHP como funções anônimas, onde não se define um nome e normalmente se utilizará por atribuir a variáveis ou atributos de classes, ou mesmo como parametrização de outras funções ou métodos, como sendo valores de funções Callback. Bem, elas fazem mais do que isso, acredite! Além disso, embora sejam tratadas como funções, na verdade são instâncias de objetos Closures. Estes objetos são tipos de primeiro nível tais como a classe stdClass. Mas, talvez se não dificultar seu entendimento, você pode tentar vê-las de dois ângulos diferentes sendo que, em um momento ela é uma função, mais em outro um objeto. Olhando primeiro do ângulo função, note o comentário do sr. Josh Lockhart:

… é uma função que encapsula o estado que a cerca no momento em que ela é criada. O estado encapsulado existe na closure…”. (LOCKHART, J; 2015, p52, grifo nosso).

Pode-se fazer muitas coisas interessantes com as funções anônimas, ainda mais quando há possibilidade de refinar a parametrização. Note esse exemplo:


function criaMensagem( $seuNome ) {

   return function( $mensagem ) use ( $seuNome ) {

        return sprintf("%s, %s", $seuNome, $mensagem);
    };
}


$fulano = criaMensagem("Alexandre");

echo $fulano("bom dia!");

Tendo essa breve explicação, podemos tratar do assunto primário deste artigo que é poder fazer referências a outros objetos e classes a partir de uma função anônima.  Isso quer dizer que você poderá fazê-lo quando utilizar closure dentro de uma classe, ou mesmo fora da classe.

Para entender isso, note esta nova função anônima, [ou closure como preferir … 🙂 ]


$closure = function() {

     return $this->getData();

};

Note que há uma referência a um método utilizando a pseudo variável $this, mas não podemos criar nenhum método dentro desta função anônima. Portanto, como ela pode referir-se a si mesma? Perceba que quando executado código para tentar imprimir a closure:


echo $closure();

Teremos um erro fatal: Fatal error: Using $this when not in object context in …

Agora pareceu não fazer sentido mesmo, a ideia do $this. Então é aí que entra o método BindTo() da classe Closure (clique aqui para ler mais sobre a classe Closure na página do Manual do PHP). Olhando agora para a closure de um ângulo de objeto, pode-se chamar métodos deste objeto no padrão: $objeto->método(). Assim, após clonar a instância do objeto closure, para… digamos uma instância aprimorada, onde se associará um objeto como sendo uma composição, dessa forma, aquele $this poderá se referir a um método existente em si próprio. Tome como exemplo a classe abaixo:


class TesteData {

    public function getData() {

        return date('d-m-Y', time());
    }
}

Esta classe contém apenas um método getData(), que retorna a data atual formatada. Note que em a função anonima exemplo, onde é exatamente este método que se faz referencia mas, por não existir causava um erro fatal. Agora acontece que quando se associa um objeto TesteData na cópia do closure, utilizando o método bindTo(), qual resultado?


$novoClosure = $closure->bindTo(new TesteData());

Note que este método não só copia o closure, bem como também associa (Bind to) um objeto TesteData ao mesmo. Agora quando se imprime o novo closure, não ocorre mais o erro fatal:


echo $novoClosure();

O método bindTo() na verdade recebe dois parâmetros, sendo que a utilização dos dois será opcional, e note que acima fora utilizado apenas um objeto.

public Closure Closure::bindTo ( object $newthis [, mixed $newscope = 'static' ] )

O primeiro parâmetro faz referência a um objeto que será utilizado para combinar com as pseudo variáveis $this. O segundo parâmetro é o escopo de classe que é usado para determinar a visibilidade dos métodos e atributos, o que será visível ou não pela closure.

Não se esqueça de comentar o que achou deste post ou apenas dê um like!

[]’s

Deixe um comentário

Preencha os seus dados abaixo ou clique em um ícone para log in:

Logotipo do WordPress.com

Você está comentando utilizando sua conta WordPress.com. Sair /  Alterar )

Foto do Google

Você está comentando utilizando sua conta Google. Sair /  Alterar )

Imagem do Twitter

Você está comentando utilizando sua conta Twitter. Sair /  Alterar )

Foto do Facebook

Você está comentando utilizando sua conta Facebook. Sair /  Alterar )

Conectando a %s

Este site utiliza o Akismet para reduzir spam. Saiba como seus dados em comentários são processados.