2008-09-08 5 views
157

PHP에서 콜백은 어떻게 작성됩니까?PHP로 콜백을 구현하려면 어떻게해야합니까?

콜백의 구현은 그렇게

// 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'); 

표시와 같이 이루어집니다

+0

이 "질문"은 더 자세하게 사용할 수 있습니다. 유용한 답변, 그래도! – rinogo

답변

157

매뉴얼은 전통적으로하지만, 상호 교환 "콜백"을 "호출" "콜백"및 용어를 사용 : 함수가있는 경우 예를 들어, 특정 기능의 경우, 당신은 확인하고보고 싶은 것 는 나중에 호출 할 함수 또는 클래스 메소드를 참조하는 function pointer과 같은 역할을하는 문자열 또는 배열 값을 나타냅니다. 이는 맛은 PHP 4 이후로 함수형 프로그래밍의 일부 요소를 허용했다 :

$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'); 

이 일반적으로 호출 값을 사용하는 안전한 방법입니다

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); 
} 

현대 PHP 버전이 허용하는 최초의 세 가지 형식 위의 코드는 직접 $cb()으로 호출됩니다. call_user_funccall_user_func_array은 위의 모든 것을 지원합니다.

참조 : http://php.net/manual/en/language.types.callable.php

주 /주의 사항 :

  1. 함수/클래스 네임 스페이스되면, 문자열이 완전한 이름을 포함해야합니다. 예 : ['Vendor\Package\Foo', 'method']
  2. call_user_func은 비 객체를 참조로 전달할 수 없으므로 call_user_func_array을 사용하거나 PHP 버전 이후에서는 콜백을 var에 저장하고 직접 구문을 사용합니다. $cb();
  3. __invoke() 메서드가있는 개체 (익명 기능 포함)는 "호출 가능"카테고리에 속하며 동일한 방식으로 사용할 수 있지만 이러한 콜백은 기존의 "콜백"용어와 직접 연관되지 않습니다.
  4. 레거시 create_function()은 전역 함수를 만들고 이름을 반환합니다. eval()에 대한 래퍼이며 익명의 함수를 대신 사용해야합니다.
+1

이것은 OP의 인정 된 자답보다 훨씬 낫습니다. – chaos

+0

사실, 함수를 사용하는 것이 올바른 방법입니다. 변수를 사용하고 그냥 호출하는 것은 허용 된 대답에 제안 된 것처럼 멋지기 때문에 추한 것이고 코드로 잘 확장되지 않습니다. – icco

+3

허용되는 답변이 변경되었습니다. 의견에 동의하면서, 이것은 훌륭한 대답입니다. –

26

: 데이터는 다음과 같습니다이 내 데이터

입니다
+16

오 마이 갓. 그게 표준인가요? 그것은 끔찍한 일이다! –

+0

위와 같이 몇 가지 다른 방법이 있습니다. 나는 정말로 같은 것을 생각했다. –

+0

와우 (Wow)는 기존 프로그래밍에 몇 가지 새로운 트위스트를 추가합니다. –

9
내가 최근에 발견 한 하나의 멋진 트릭 익명을 만들기 위해 PHP의 create_function()를 사용하는 것입니다

/람다 함수를 한 번 사용합니다. array_map(), preg_replace_callback() 또는 usort()과 같이 사용자 정의 처리를 위해 콜백을 사용하는 PHP 함수에 유용합니다. 커버 아래에있는 eval()처럼 보이지만 여전히 PHP를 사용하는 멋진 기능 스타일 방식입니다.

+6

불행히도 가비지 수집기는 잠재적 인 메모리 누수를 일으키는이 구조로는 잘 재생되지 않습니다. 성능이 떨어지면 create_function()을 피하십시오. – fuxia

+1

아참. 헤즈 업에 감사드립니다. – yukondude

3

나는 언제든지 create_function()을 PHP로 사용합니다.

매개 변수는 쉼표로 구분 된 문자열입니다. 문자열의 전체 기능 본문 ... 아 ... 나는 시도한 경우에도 더 못생긴 것으로 생각합니다.

명명 된 함수를 만들면 문제가되지 않는 유일한 선택입니다. 5.3, 우리가 그들과 함께 익명 함수

http://wiki.php.net/rfc/closures

+0

그리고 물론, 런타임 문자열 eval이기 때문에 컴파일시 유효한 구문이나 다른 것을 검사하지 않습니다. – hobbs

7

잘 ... 수평선에 5.3으로, 모든 당신은 무엇이든 전화를 확인하려는 것, 더 나은 것 유효합니다.

function doIt($callback) { 
    if(function_exists($callback)) { 
     $callback(); 
    } else { 
     // some error handling 
    } 
} 
7

을 폐쇄을 얻을 것이기 때문에

+0

콜백이 함수가 아니라 객체 및 메서드를 포함하는 배열 인 경우 어떻게해야합니까? –

+0

또는 오히려'is_callable ($ callback) ' –

+0

두 가지 모두 좋은 제안입니다. 콜백 수행 방법에 대한 자신 만의 특정 구현을 확인해야합니다. 나는 치명적인 결과를 초래하지 않은 것을 부르는 것에 대해 경고하기를 희망했다. 대답을 좀 더 일반적인 것으로 만들었습니다 – SeanDowney

4

create_function은 클래스 내에서 작동하지 않습니다. call_user_func을 사용해야했습니다. 그런 다음

<?php 

class Dispatcher { 
    //Added explicit callback declaration. 
    var $callback; 

    public function Dispatcher($callback){ 
     $this->callback = $callback; 
    } 

    public function asynchronous_method(){ 
     //do asynch stuff, like fwrite...then, fire callback. 
     if (isset($this->callback)) { 
      if (function_exists($this->callback)) call_user_func($this->callback, "File done!"); 
     } 
    } 

} 

는 사용하기 :

<?php 
include_once('Dispatcher.php'); 
$d = new Dispatcher('do_callback'); 
$d->asynchronous_method(); 

function do_callback($data){ 
    print 'Data is: ' . $data . "\n"; 
} 
?> 

[편집] 추가 누락 된 괄호. 또한 콜백 선언을 추가했습니다. 나는 그렇게 선호합니다.

+1

Dispatcher 클래스가 $ this-> callback = $ callback이 작동하려면 속성이 필요하지 않습니까? –

+0

@james poulson : PHP는 동적 언어이므로 작동합니다. 하지만 나는 게으르다. 나는 대개 속성을 선언하고 모든 사람의 삶을 편하게 만듭니다. 귀하의 질문은 저에게 그 코드를 다시 보게하고 구문 오류를 발견했습니다. 감사합니다 – goliatone

+0

나는 이것이 가능하다는 것을 몰랐습니다. 답변 해주셔서 감사합니다 :) . –

59

PHP 5.3로, 당신은 지금이 작업을 수행 할 수 있습니다 그것을 할 수

function doIt($callback) { $callback(); } 

doIt(function() { 
    // this will be done 
}); 

마지막으로 좋은 방법입니다. 콜백이 굉장하기 때문에 PHP에 큰 도움이됩니다.

+4

매우 유용하며 매우 유용합니다. – Ulterior

1

PHP < 5.4과의 호환성을 걱정하지 않는 분들을 위해 더 나은 구현을 위해 유형 힌팅을 사용하시기 바랍니다.

function call_with_hello_and_append_world(callable $callback) 
{ 
    // No need to check $closure because of the type hint 
    return $callback("hello")."world"; 
} 

function append_space($string) 
{ 
    return $string." "; 
} 

$output1 = call_with_hello_and_append_world(function($string) { return $string." "; }); 
var_dump($output1); // string(11) "hello world" 

$output2 = call_with_hello_and_append_world("append_space"); 
var_dump($output2); // string(11) "hello world" 

$old_lambda = create_function('$string', 'return $string." ";'); 
$output3 = call_with_hello_and_append_world($old_lambda); 
var_dump($output3); // string(11) "hello world" 
관련 문제