2015-09-08 18 views
9

Di solito in PHP se si dispone di un metodo di una classe barFoo e vuoi farla passare intorno come un callable, è usare qualcosa comePHP - metodo Callable non come array di

$foo = new Foo(); 
$callable = [$foo, 'bar']; 

Il rovescio della medaglia questo è che is_array($callable) restituisce true.

Esiste un altro metodo percorribile per passare un metodo di classe come un chiamabile in modo che is_array($callable) restituisca false?

+5

perché è un aspetto negativo? –

+0

@HalayemAnis Capisco che non è un chiaro svantaggio, ma lo vedo come uno perché non mi aspetto che un callable sia un array. Sembra qualcosa di simile a un dettaglio di implementazione che non dovrebbe essere passato attorno allo – marcosh

risposta

10

Sì, c'è ... anche se si tratta di un orribile, orribile trucco:

$foo = new Foo(); 

function makeCallable($instance, $method) 
{ 
    return function() use ($instance, $method) { 
     return $instance->{$method}();//use func_get_args + call_user_func_array to support arguments 
    }; 
} 

quindi è possibile utilizzare:

$callable = makeCallable($foo, 'bar'); 
var_dump(is_array($callable));//false 

Lo svantaggio è che:

var_dump($callbale instanceof Closure);//true 

Fondamentalmente, non prestare attenzione al fatto che il tuo callable è anche un array, e basta usare il suggerimento del tipo nel tuo codice base:

function foobar(callable $action) 
{ 
    return call_user_func($action); 
} 

Questo dovrebbe funzionare bene.

Sul motivo per cui ritieni che l'attuale serie callable sia un aspetto negativo: capisco perché ritieni che questa non sia una buona cosa. Non c'è davvero bisogno per nessuno di sapere che un particolare costrutto chiamabile è un array, una stringa o una funzione anonima (che in realtà è un'istanza della classe Closure - un altro dettaglio di implementazione che potresti non voler passare in giro). Ma è esattamente perché i costrutti callable si presentano in molte forme, esiste il suggerimento tipo callable: il codice che scrivi che richiede un callable non deve preoccuparsi di come viene implementata quell'entità chiamabile, basta sapere che può chiamare quel pezzo di informazioni:

function handleEvent(callable $action, array $args = null) 
{ 
    if ($args) { 
     return call_user_func_array($action, $args); 
    } 
    return call_user_fun($action); 
} 

non c'è bisogno di me per controllare se $action è una stringa (come 'strtolower', un'istanza Closure o un array) ho appena so mi può chiamare

+0

che sembra davvero un hack! Grazie per la risposta – marcosh

+0

@marcosh: stavo scrivendo una breve rant sul perché non dovresti davvero preoccuparti di come si presenta il callable: ci sono molti costrutti callable/callback validi in PHP, solo uno dei quali è un array –

+0

appena letto è molto chiaro e informativo! Grazie ancora – marcosh

4

funzioni ei metodi non sono cittadini di prima classe in PHP, cioè non possono essere assig ned variabili, non hanno un tipo ecc

callable non è in realtà un tipo, is_callable così come il tipo di suggerimento callable solo controlla se qualcosa può essere utilizzata come funzione.Questo può essere:

  • un array [class, method] per un metodo statico
  • una matrice [object, method] per un metodo di istanza
  • una stringa per una funzione
  • un Closure esempio
  • un oggetto che implementa la magia metodo __invoke()

Come vedete, tutti questi valori sono validi hai un tipo diverso e capita di essere "callable". Non esiste un callable "puro" che non abbia un altro tipo.