2014-10-01 25 views
6

Moja funkcja prepare(), ma definicję:Dlaczego przekazywanie zmiennej przez odwołanie nie działa podczas wywoływania metody refleksyjnej?

private function prepare (& $ data, $ conditions = null, $ conditionsRequired = false)

Kiedy go przetestować, to

/** 
    * @covers /data/DB_Service::prepare 
    * @uses /inc/config 
    */ 
    public function testNoExceptionIsRaisedForValidPrepareWithConditionsAndConditionsRequiredArguments() { 
    $method = new ReflectionMethod('DB_Service', 'prepare'); 
    $method->setAccessible(TRUE); 

    $dbs = new DB_Service(new Config(), array('admin', 'etl')); 
    $data = array('message' => '', 'sql' => array('full_query' => "")); 
    $method->invoke($dbs, $data, array('conditionKey' => 'conditionValue'), TRUE); 
    } 

podbicia (i łamie mi test)

ReflectionException: Inwokacja metoda DB_Service :: prepare() nie

Jednak ten

/** 
    * @covers /data/DB_Service::prepare 
    * @uses /inc/config 
    */ 
    public function testNoExceptionIsRaisedForValidPrepareWithConditionsAndConditionsRequiredArguments() { 
    $method = new ReflectionMethod('DB_Service', 'prepare'); 
    $method->setAccessible(TRUE); 

    $dbs = new DB_Service(new Config(), array('admin', 'etl')); 
    //$data is no longer declared - the array is directly in the call below 
    $method->invoke($dbs, array('message' => '', 'sql' => array('full_query' => "")), array('conditionKey' => 'conditionValue'), TRUE); 
    } 

działa idealnie, a test jest udany.

Dlaczego zadeklarowanie zmiennej, a następnie przekazanie nie działa, ale po prostu tworzenie jej w wywołaniu metody działa? Myślę, że ma to coś wspólnego z tym, jak działa invoke(), ale nie potrafię wymyślić czego.

Odpowiedz

8

Z dokumentacji dla invoke:

Uwaga: Jeśli funkcja ma argumentów, które muszą być referencje, a następnie muszą być odniesienia w wykazie przekazany argumentów.

Więc twój pierwszy przykład powinien działać, jeśli go zmienić na:

$method->invoke($dbs, &$data, array('conditionKey' => 'conditionValue'), TRUE); 

EDIT: Aby uniknąć przestarzałej czas połączenia przechodzą przez referencję, można użyć tablicę i invokeArgs:

$method->invokeArgs($dbs, array(&$data, array('conditionKey' => 'conditionValue'), TRUE)); 
+0

Na [ten adres SO] (http://stackoverflow.com/questions/8971261/php-5-4-call-time-pass-by-reference-easy-fix-available), jest to przestarzałe w PHP5 i jego użycie jest odradzane. W definicji metody przekazuję argument przez odwołanie, więc ponowne wywoływanie w wywołaniu nie powinno być poprawne. –

+0

@MatthewHerbst Masz całkowitą rację, mój błąd. – wavemode

+0

Ach, to invokeArgs jest świetne. Dziękuję Ci! –