Chciałbym móc wywołać zamknięcie, które przypisuję bezpośrednio do właściwości obiektu, bez ponownego przypisywania zamknięcia do zmiennej, a następnie wywoływania jej. czy to możliwe?
Poniższy kod nie działa i powoduje Fatal error: Call to undefined method stdClass::callback()
.
$obj = new stdClass();
$obj->callback = function() {
print "HelloWorld!";
};
$obj->callback();
php
object
properties
closures
Kendall Hopkins
źródło
źródło
Odpowiedzi:
Od PHP7 możesz to zrobić
lub użyj Closure :: call () , chociaż to nie działa na
StdClass
.Przed PHP7 musiałbyś zaimplementować magiczną
__call
metodę, aby przechwycić wywołanie i wywołać wywołanie zwrotne (coStdClass
oczywiście nie jest możliwe , ponieważ nie możesz dodać__call
metody)Pamiętaj, że nie możesz tego zrobić
w
__call
ciele, ponieważ wywołałoby__call
to nieskończoną pętlę.źródło
Możesz to zrobić, wywołując __invoke przy zamykaniu, ponieważ jest to magiczna metoda, której używają obiekty, aby zachowywać się jak funkcje:
Oczywiście to nie zadziała, jeśli wywołanie zwrotne jest tablicą lub ciągiem znaków (które mogą być również prawidłowymi wywołaniami zwrotnymi w PHP) - tylko dla zamknięć i innych obiektów z zachowaniem __invoke.
źródło
call_user_func($obj->callback)
nie jest tak źle.call_user_func
działa też ze strunami i nie zawsze jest to wygodne$obj->callback->__invoke();
gdy można by się tego spodziewać$obj->callback()
. To tylko kwestia spójności.$obj->callback instanceof \Closure
.Od PHP 7 możesz wykonać następujące czynności:
źródło
Od PHP 7 domknięcie można wywołać
call()
metodą:Ponieważ PHP 7 jest możliwe do wykonywania operacji również na dowolnych
(...)
wyrażeniach (jak wyjaśniono w Korikulum ):Inne popularne podejścia do PHP 5 to:
używając magicznej metody
__invoke()
(jak wyjaśnił Brilliand )za pomocą
call_user_func()
funkcjiużycie zmiennej pośredniej w wyrażeniu
Każdy sposób ma swoje wady i zalety, ale najbardziej radykalnym i ostatecznym rozwiązaniem pozostaje to, które przedstawił Gordon .
źródło
Wydaje się, że jest to możliwe przy użyciu
call_user_func()
.choć nie eleganckie ... To, co mówi @Gordon, jest prawdopodobnie jedyną drogą.
źródło
Cóż, jeśli naprawdę nalegasz. Innym obejściem byłoby:
Ale to nie jest najładniejsza składnia.
Jednakże parsera PHP zawsze traktuje
T_OBJECT_OPERATOR
,IDENTIFIER
,(
jako metoda połączenia. Wydaje się, że nie ma obejścia umożliwiającego->
ominięcie tabeli metod i uzyskanie dostępu do atrybutów.źródło
Wiem, że to jest stare, ale myślę, że funkcje ładnie radzą sobie z tym problemem, jeśli używasz PHP 5.4+
Najpierw utwórz cechę, która umożliwia wywołanie właściwości:
Następnie możesz użyć tej cechy na swoich zajęciach:
Teraz możesz definiować właściwości za pomocą funkcji anonimowych i wywoływać je bezpośrednio:
źródło
cóż, należy podkreślić, że przechowywanie zamknięcia w zmiennej i wywołanie zmiennej jest faktycznie (dziwnie) szybsze, w zależności od kwoty połączenia, staje się całkiem sporo, z xdebug (tak bardzo precyzyjnym pomiarem), o którym mówimy 1,5 (współczynnik, używając zmiennej, zamiast bezpośrednio wywoływać __invoke, więc zamiast tego po prostu zapisz zamknięcie w zmiennej i wywołaj ją.
źródło
Oto kolejna alternatywa oparta na zaakceptowanej odpowiedzi, ale bezpośrednio rozszerzająca stdClass:
Przykład użycia:
Prawdopodobnie lepiej jest użyć
call_user_func
lub__invoke
chociaż.źródło
Zaktualizowano:
PHP> = 7:
PHP> = 5,4:
źródło
Call to undefined method AnyObject::callback()
(Oczywiście klasa AnyObject istnieje.)Jeśli używasz PHP 5.4 lub nowszego, możesz powiązać wywołanie z zakresem swojego obiektu, aby wywołać niestandardowe zachowanie. Na przykład, jeśli miałbyś skonfigurować następującą konfigurację ...
A ty działałeś na takiej klasie ...
Możesz uruchomić własną logikę, tak jakbyś działał z zakresu swojego obiektu
źródło
Zauważam, że działa to w PHP5.5
Umożliwia tworzenie kolekcji domknięć typu pseudo-obiektowego.
źródło