Połączę kolejne pytanie z tym, ponieważ próbowałem ogłosić zamknięcie.
akinuri
Odpowiedzi:
173
Podręcznik używa terminów „callback” i „callable” zamiennie, jednak „callback” tradycyjnie odnosi się do wartości ciągu lub tablicy, która działa jak wskaźnik funkcji , odwołując się do funkcji lub metody klasy do przyszłego wywołania. Pozwoliło to na niektóre elementy programowania funkcjonalnego od PHP 4. Smaki są następujące:
$cb1 ='someGlobalFunction';
$cb2 =['ClassName','someStaticMethod'];
$cb3 =[$object,'somePublicMethod'];// this syntax is callable since PHP 5.2.3 but a string containing it// cannot be called directly
$cb2 ='ClassName::someStaticMethod';
$cb2();// fatal error// legacy syntax for PHP 4
$cb3 = array(&$object,'somePublicMethod');
Jest to bezpieczny sposób na używanie ogólnie dostępnych wartości:
if(is_callable($cb2)){// Autoloading will be invoked to load the class "ClassName" if it's not// yet defined, and PHP will check that the class has a method// "someStaticMethod". Note that is_callable() will NOT verify that the// method can safely be executed in static context.
$returnValue = call_user_func($cb2, $arg1, $arg2);}
Nowoczesne wersje PHP pozwalają wywoływać trzy pierwsze formaty powyżej bezpośrednio jako $cb(). call_user_funci call_user_func_arraywesprzyj wszystkie powyższe.
Jeśli funkcja / klasa ma przestrzeń nazw, ciąg musi zawierać pełną nazwę. Na przykład['Vendor\Package\Foo', 'method']
call_user_funcnie obsługuje przekazywania obiektów niebędących obiektami przez referencję, więc możesz użyć call_user_func_arraylub, w późniejszych wersjach PHP, zapisać wywołanie zwrotne w zmiennej var i użyć bezpośredniej składni:$cb() ;
Obiekty z __invoke()metodą (w tym funkcje anonimowe) należą do kategorii „wywoływalne” i mogą być używane w ten sam sposób, ale ja osobiście nie kojarzę ich ze starszym terminem „wywołanie zwrotne”.
Dziedzictwo create_function()tworzy funkcję globalną i zwraca jej nazwę. Jest to opakowanie dla eval()i zamiast tego należy użyć funkcji anonimowych.
Rzeczywiście, użycie tej funkcji jest właściwym sposobem na zrobienie tego. Podczas korzystania ze zmiennej, a następnie po prostu jej wywoływania, jak sugeruje zaakceptowana odpowiedź, jest fajna, jest brzydka i nie da się dobrze skalować z kodem.
icco
4
Zmieniono zaakceptowaną odpowiedź. Zgadzając się z komentarzami, jest to świetna odpowiedź.
Nick Stinemon,
Przydałoby się czytelnikom pochodzącym z programowania w języku Python wskazanie w odpowiedzi, że 'someGlobalFunction'rzeczywiście jest to zdefiniowana funkcja.
TMOTTM
1
Począwszy od PHP 5.3, istnieją zamknięcia, patrz odpowiedź Bart van Heukelom . Jest o wiele prostszy i „standardowy” niż cały ten stary bałagan.
naprawde
Tak, w mojej odpowiedzi wspominam o funkcjach anonimowych, ale OP poprosił o „callback” (w 2008 roku), a te starsze style callbacków są nadal bardzo popularne w tonach baz kodu PHP.
Steve Clay
74
W PHP 5.3 możesz teraz to zrobić:
function doIt($callback){ $callback();}
doIt(function(){// this will be done});
Wreszcie fajny sposób na zrobienie tego. Świetny dodatek do PHP, ponieważ wywołania zwrotne są niesamowite.
Implementacja wywołania zwrotnego odbywa się w ten sposób
// This function uses a callback function. function doIt($callback){
$data ="this is my data";
$callback($data);}// This is a sample callback function for doIt(). function myCallback($data){print'Data is: '. $data ."\n";}// Call doIt() and pass our sample callback function's name.
doIt('myCallback');
Istnieje kilka innych sposobów, jak to pokazano powyżej. Naprawdę myślałem tak samo.
Nick Stinemon,
3
@Nick Retallack, nie rozumiem, co jest w tym tak okropnego. W przypadku języków, które znam, takich jak JavaScript i C #, wszystkie one mogą ustrukturyzować swoją funkcję zwrotną w taki sposób. Pochodzę z JavaScirpt i C #, tak naprawdę nie jestem przyzwyczajony do call_user_func (). Czuję, że muszę się dostosować do PHP, zamiast na odwrót.
Antony
4
@Antony Sprzeciwiłem się temu, że ciągi są wskaźnikami funkcji w tym języku. Zamieściłem ten komentarz trzy lata temu, więc jestem już do tego przyzwyczajony, ale myślę, że PHP jest jedynym znanym mi językiem (innym niż skryptowanie powłoki), w którym tak jest.
Nick Retallack,
1
@Antony Wolę używać tej samej składni, której używam w javascript. Więc nawet nie rozumiem, dlaczego ludzie chcą korzystać, call_user_func()gdy mają składnię, która umożliwia im dynamiczne wywoływanie funkcji i wykonywanie połączeń zwrotnych. Zgadzam się z Tobą!
botenvouwer
9
Jedną z fajnych sztuczek, które ostatnio znalazłem, jest użycie PHP create_function()do stworzenia anonimowej / lambda funkcji do jednorazowego użycia. Jest to użyteczne dla funkcji PHP, takich jak array_map(), preg_replace_callback()lub usort(), że używają wywołań zwrotnych do przetwarzania niestandardowej. Wygląda prawie tak, jakby eval()działał pod przykryciem, ale nadal jest to przyjemny funkcjonalny sposób używania PHP.
Niestety, śmieciarz nie działa zbyt dobrze z tym konstruktem, powodując potencjalne wycieki pamięci. Jeśli zależy Ci na wydajności, unikaj funkcji create_function ().
fuxia
1
Auć. Dzięki za zgłoszenie się.
yukondude
Czy mógłbyś zaktualizować odpowiedź w wersji PHP 7.4 (funkcje strzałek) i dodać ostrzeżenie o przestarzałym create_function()?
Dharman
7
cóż ... z 5.3 na horyzoncie wszystko będzie lepiej, ponieważ z 5.3 otrzymamy zamknięcia, a wraz z nimi anonimowe funkcje
Będziesz chciał zweryfikować, czy Twoje połączenie jest prawidłowe. Na przykład w przypadku określonej funkcji będziesz chciał sprawdzić i sprawdzić, czy funkcja istnieje:
function doIt($callback){if(function_exists($callback)){
$callback();}else{// some error handling}}
Co jeśli wywołanie zwrotne nie jest funkcją, ale tablicą przechowującą obiekt i metodę?
d -_- b
3
a raczejis_callable( $callback )
Roko C. Buljan
1
Oba są dobrymi sugestiami - Konieczne będzie sprawdzenie własnej implementacji sposobu wykonywania oddzwaniania. Miałem nadzieję ostrzec przed wezwaniem czegoś, co nie istniało, powodując śmierć.
Uczyniłem
5
create_functionnie działało dla mnie w klasie. Musiałem użyć call_user_func.
Czy klasa Dispatcher nie wymaga atrybutu, aby $ this-> callback = $ callback działał?
James P.
@james poulson: PHP jest językiem dynamicznym, więc działa. Ale byłem leniwy. Zwykle deklaruję właściwości, ułatwia wszystkim życie. Twoje pytanie sprawiło, że ponownie spojrzałem na ten kod i zauważyłem błąd składniowy. Dzięki
goliatone,
Nie wiedziałem, że to możliwe. Dziękuję za odpowiedź :) .
James P.
Czy nie byłoby bezpieczniej zadeklarować funkcję do_callback przed utworzeniem obiektu Dispatcher i wywołaniem metody asynchronicznej?
ejectamenta
3
Kulę się za każdym razem, gdy używam create_function()w php.
Parametry to ciąg rozdzielony przecinkami, całe ciało funkcji w ciągu ... Argh ... Myślę, że nie mogliby uczynić go brzydszym, nawet gdyby próbowali.
Niestety jest to jedyny wybór, gdy utworzenie nazwanej funkcji nie jest warte kłopotu.
Odpowiedzi:
Podręcznik używa terminów „callback” i „callable” zamiennie, jednak „callback” tradycyjnie odnosi się do wartości ciągu lub tablicy, która działa jak wskaźnik funkcji , odwołując się do funkcji lub metody klasy do przyszłego wywołania. Pozwoliło to na niektóre elementy programowania funkcjonalnego od PHP 4. Smaki są następujące:
Jest to bezpieczny sposób na używanie ogólnie dostępnych wartości:
Nowoczesne wersje PHP pozwalają wywoływać trzy pierwsze formaty powyżej bezpośrednio jako
$cb()
.call_user_func
icall_user_func_array
wesprzyj wszystkie powyższe.Zobacz: http://php.net/manual/en/language.types.callable.php
Uwagi / zastrzeżenia:
['Vendor\Package\Foo', 'method']
call_user_func
nie obsługuje przekazywania obiektów niebędących obiektami przez referencję, więc możesz użyćcall_user_func_array
lub, w późniejszych wersjach PHP, zapisać wywołanie zwrotne w zmiennej var i użyć bezpośredniej składni:$cb()
;__invoke()
metodą (w tym funkcje anonimowe) należą do kategorii „wywoływalne” i mogą być używane w ten sam sposób, ale ja osobiście nie kojarzę ich ze starszym terminem „wywołanie zwrotne”.create_function()
tworzy funkcję globalną i zwraca jej nazwę. Jest to opakowanie dlaeval()
i zamiast tego należy użyć funkcji anonimowych.źródło
'someGlobalFunction'
rzeczywiście jest to zdefiniowana funkcja.W PHP 5.3 możesz teraz to zrobić:
Wreszcie fajny sposób na zrobienie tego. Świetny dodatek do PHP, ponieważ wywołania zwrotne są niesamowite.
źródło
Implementacja wywołania zwrotnego odbywa się w ten sposób
Wyświetla: Dane to: to moje dane
źródło
call_user_func()
gdy mają składnię, która umożliwia im dynamiczne wywoływanie funkcji i wykonywanie połączeń zwrotnych. Zgadzam się z Tobą!Jedną z fajnych sztuczek, które ostatnio znalazłem, jest użycie PHP
create_function()
do stworzenia anonimowej / lambda funkcji do jednorazowego użycia. Jest to użyteczne dla funkcji PHP, takich jakarray_map()
,preg_replace_callback()
lubusort()
, że używają wywołań zwrotnych do przetwarzania niestandardowej. Wygląda prawie tak, jakbyeval()
działał pod przykryciem, ale nadal jest to przyjemny funkcjonalny sposób używania PHP.źródło
create_function()
?cóż ... z 5.3 na horyzoncie wszystko będzie lepiej, ponieważ z 5.3 otrzymamy zamknięcia, a wraz z nimi anonimowe funkcje
http://wiki.php.net/rfc/closures
źródło
Będziesz chciał zweryfikować, czy Twoje połączenie jest prawidłowe. Na przykład w przypadku określonej funkcji będziesz chciał sprawdzić i sprawdzić, czy funkcja istnieje:
źródło
is_callable( $callback )
create_function
nie działało dla mnie w klasie. Musiałem użyćcall_user_func
.Następnie, aby użyć:
[Edytuj] Dodano brakujący nawias. Ponadto dodano deklarację oddzwonienia, wolę to w ten sposób.
źródło
Kulę się za każdym razem, gdy używam
create_function()
w php.Parametry to ciąg rozdzielony przecinkami, całe ciało funkcji w ciągu ... Argh ... Myślę, że nie mogliby uczynić go brzydszym, nawet gdyby próbowali.
Niestety jest to jedyny wybór, gdy utworzenie nazwanej funkcji nie jest warte kłopotu.
źródło
create_function()
jest teraz przestarzałe i nie należy go używać.Dla tych, którym nie zależy na zerwaniu kompatybilności z PHP
< 5.4
, sugeruję użycie podpowiedzi typu, aby uzyskać czystszą implementację.źródło
create_function()
zostało DEPRECATED od PHP 7.2.0. Poleganie na tej funkcji jest wysoce odradzane.