8

My function, prepare(), has the definition:

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

When I test it, this

  /**
  * @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);
  }

raises (and breaks my test)

ReflectionException: Invocation of method DB_Service::prepare() failed

However, this

  /**
  * @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);
  }

works perfectly and the test is successful.

Why does declaring the variable and then passing not work, but simply creating it in the method call does work? I think this has something to do with how invoke() works, but I can't seem to figure out what.

Matthew Herbst
  • 29,477
  • 23
  • 85
  • 128

1 Answers1

14

From the documentation for invoke:

Note: If the function has arguments that need to be references, then they must be references in the passed argument list.

So, your first example should work if you change it to:

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

EDIT: To avoid deprecated call time pass-by-reference, you can use an array and invokeArgs:

$method->invokeArgs($dbs, array(&$data, array('conditionKey' => 'conditionValue'), TRUE));
wavemode
  • 2,076
  • 1
  • 19
  • 24
  • Per [this SO post](http://stackoverflow.com/questions/8971261/php-5-4-call-time-pass-by-reference-easy-fix-available), this is deprecated in PHP5 and it's use is discouraged. In the method definition I pass the argument by reference, so doing so again in the call shouldn't be correct. – Matthew Herbst Oct 01 '14 at 04:16
  • @MatthewHerbst You're absolutely right, my mistake. – wavemode Oct 01 '14 at 04:21
  • Ah, that invokeArgs is great. Thank you! – Matthew Herbst Oct 01 '14 at 04:44