Gostaria de poder chamar um encerramento que atribuo à propriedade de um objeto diretamente, sem reatribuir o encerramento a uma variável e, em seguida, chamá-lo. Isso é possível?
O código abaixo não funciona e faz com que Fatal error: Call to undefined method stdClass::callback()
.
$obj = new stdClass();
$obj->callback = function() {
print "HelloWorld!";
};
$obj->callback();
php
object
properties
closures
Kendall Hopkins
fonte
fonte
Respostas:
A partir do PHP7, você pode fazer
ou use Closure :: call () , embora isso não funcione em a
StdClass
.Antes do PHP7, você teria que implementar o
__call
método mágico para interceptar a chamada e invocar o retorno de chamada (o que não é possívelStdClass
, é claro, porque você não pode adicionar o__call
método)Observe que você não pode fazer
no
__call
corpo, porque isso dispararia__call
em um loop infinito.fonte
Você pode fazer isso chamando __invoke na closure, pois esse é o método mágico que os objetos usam para se comportar como funções:
É claro que isso não funcionará se o callback for um array ou string (que também podem ser callbacks válidos em PHP) - apenas para closures e outros objetos com comportamento __invoke.
fonte
call_user_func($obj->callback)
não é tão ruim assim.call_user_func
funciona com cordas e isso nem sempre é conveniente$obj->callback->__invoke();
quando se esperava que fosse$obj->callback()
. É apenas uma questão de consistência.$obj->callback instanceof \Closure
.A partir do PHP 7, você pode fazer o seguinte:
fonte
Desde o PHP 7, um encerramento pode ser chamado usando o
call()
método:Já que o PHP 7 também é possível executar operações em
(...)
expressões arbitrárias (conforme explicado por Korikulum ):Outras abordagens comuns do PHP 5 são:
usando o método mágico
__invoke()
(conforme explicado por Brilliand )usando a
call_user_func()
funçãousando uma variável intermediária em uma expressão
Cada caminho tem seus prós e contras, mas a solução mais radical e definitiva ainda é a apresentada por Gordon .
fonte
Parece ser possível usar
call_user_func()
.não é elegante, entretanto ... O que @Gordon diz é provavelmente o único caminho a percorrer.
fonte
Bem, se você realmente insiste. Outra solução alternativa seria:
Mas essa não é a sintaxe mais agradável.
No entanto, o analisador PHP sempre trata
T_OBJECT_OPERATOR
,IDENTIFIER
,(
como chamada de método. Parece não haver uma solução alternativa para->
evitar a tabela de métodos e acessar os atributos.fonte
Eu sei que isso é antigo, mas acho que o Traits resolve bem esse problema se você estiver usando PHP 5.4+
Primeiro, crie uma característica que torne as propriedades chamáveis:
Então, você pode usar essa característica em suas aulas:
Agora, você pode definir propriedades por meio de funções anônimas e chamá-las diretamente:
fonte
bem, deve-se enfatizar que armazenar o fechamento em uma variável e chamar a variável é na verdade (estranhamente) mais rápido, dependendo do valor da chamada, torna-se bastante, com xdebug (medição muito precisa), estamos falando 1,5 (o fator, usando uma variável, em vez de chamar diretamente o __invoke. Então, em vez disso, apenas armazene o encerramento em uma variável e chame-a.
fonte
Atualizada:
PHP> = 7:
PHP> = 5,4:
fonte
Call to undefined method AnyObject::callback()
(A classe AnyObject existe, é claro.)Aqui está outra alternativa com base na resposta aceita, mas estendendo stdClass diretamente:
Exemplo de uso:
Você provavelmente está melhor usando
call_user_func
ou__invoke
embora.fonte
Se você estiver usando PHP 5.4 ou superior, poderá vincular um chamável ao escopo do seu objeto para invocar o comportamento personalizado. Por exemplo, se você tivesse a seguinte configuração ..
E você estava operando em uma classe assim ..
Você pode executar sua própria lógica como se estivesse operando dentro do escopo de seu objeto
fonte
Noto que isso funciona no PHP5.5
Permite criar uma coleção de fechamentos de objetos psuedo.
fonte