Edit report at http://bugs.php.net/bug.php?id=51284&edit=1
ID: 51284 User updated by: gerhard at tinned-software dot net Reported by: gerhard at tinned-software dot net Summary: foreach distroys objects in array Status: Bogus Type: Bug Package: Class/Object related Operating System: MacOSX, Linux, ... PHP Version: Irrelevant New Comment: Thanks, that solved it. Thanks for that. Its now the second time i commit a bug to php and as the first time it was immediately closed as Bogus without having a closer look to it. I don't know how much bug reports you have to review every day, but i hope you will have at least a closer look next time i report a bug. Previous Comments: ------------------------------------------------------------------------ [2010-05-20 10:20:47] gerhard at tinned-software dot net So my assumption seems to be correct that it has to do with the foreach loop. I will follow your suggestion and try the loop with a & for the second parameter. But in general, ... Wouldn't it be an idea to maybe place a line in the documentation for that? ------------------------------------------------------------------------ [2010-05-20 08:17:18] m...@php.net That's true, sorry. You lose the reference because of foreach; try: foreach ($parameter as $key => &$param) ... ------------------------------------------------------------------------ [2010-05-19 17:45:19] gerhard at tinned-software dot net This comment is simply not true!!! How can it be that the function call func_get_args() destroys the reference when one of this functions work and the other function does not work? Both functions use this functionb call. But only in the function get_object_NOK() the error message is shown. In the other function, the object is created as expected. So please explain me how the function call func_get_args() can cause this? ------------------------------------------------------------------------ [2010-05-19 15:23:49] m...@php.net I get a Warning: Parameter 2 to test_obj2::__construct() expected to be a reference, value given in /tmp/phpbugs/51284.php on line 128 You lose the ref with func_get_args(). ------------------------------------------------------------------------ [2010-03-12 13:29:44] gerhard at tinned-software dot net Description: ------------ I have a script which tries to create configured objects of classes. The method creating the object of the named class will generate a unique identifier to be able to identify the invocation later in the class. This unique_id is basically calculated by adding the class name and all constructor parameters into a ":"-seperetaed list. For doing this i used This all functions well as long as there is not the following very special combination of parameters and class-parameterlist. If one of the parameters is an object, and this object is passed to the class as reference (&$object). In such a case, the foreach loop destroys somehow the $parameter array. As the $parameter array is not altered in the loop, there is no explanation to my way the loop influence the array. To prove that the loop is causing this problem i changed the loop from foreach() to for(). As you can see in the test script there are 2 methods in the OM class. The get_object_OK() uses the for()-loop to generate the ID and the get_object_NOK() method uses the foreach()-loop to generate it. With the for()-loop the script runs without any troubles. But with the foreach()-loop the script returns an error while invocating the object. This error causes the object to be not created. The error message which can be found in the webserver's / php's logfile is the following: [error] [client 127.0.0.1] PHP Warning: Invocation of test_obj2's constructor failed in /.../test.php on line 183, referer: http://127.0.0.1:8080/ ... The line references to "$obj = $reflection_obj->newInstanceArgs($parameter);" at the get_object_NOK.() function. Test script: --------------- class test_obj { var $test = "abc"; function __construct($str) { $this->test = $str; } function get() { echo get_class($this)." - string=".$this->test."<br />\n"; } function set($str) { $test = $str; } } class test_obj2 { var $test = "abc"; function __construct($string1, &$object) { echo get_class($this)." - string1=$string1<br />\n"; $object->get(); } } //include_once(dirname(__FILE__).'/object_manager.class.php'); //include_once(dirname(__FILE__).'/element_container.class.php'); // // Test execution // echo "PHP Version: ".phpversion()."<br /><br />\n"; $om = new OM(); $t1 = new test_obj("init-text-object-1"); $t1->get(); echo "Object of class 'Test_CLass' ... Finished.<br />\n"; $t2 = $om->get_object_OK("test_obj2", "object-text-2", $t1); echo "Object of class 'Test_CLass2' with for() loop ... Finished.<br />\n"; $t2 = $om->get_object_NOK("test_obj2", "object-text-2", $t1); echo "Object of class 'Test_CLass2' with foreach() loop ... Finished.<br />\n"; // // A short testing code from a much biger function / Class to // demonstrate the behaviour // class OM { function get_object_OK() { $parameter = func_get_args(); $type = array_shift($parameter); // // create unique identifier for this object creation. // Used in the original class to identify the object later in the class. // $unique_id = "$type:"; // loop through all parameters for($i=0; $i < count($parameter); $i++) { // if parameter is an object, get only the object name if(is_object($parameter[$i]) === TRUE) { $unique_id .= get_class($parameter[$i]).':'; continue; } // get the variable content as string to the identifier-string $unique_id .= gettype($parameter[$i]).':'; } // // Creating the object by name // $reflection_obj = new ReflectionClass($type); $obj = $reflection_obj->newInstanceArgs($parameter); // return the created object return $obj; } function get_object_NOK() { $parameter = func_get_args(); $type = array_shift($parameter); // // create unique identifier for this object creation. // Used in the original class to identify the object later in the class. // $unique_id = "$type:"; // loop through all parameters foreach($parameter as $key => $param) { // if parameter is an object, get only the object name if(is_object($param) === TRUE) { $unique_id .= get_class($param).':'; continue; } // get the variable content as string to the identifier-string $unique_id .= gettype($param).':'; } // // Creating the object by name // $reflection_obj = new ReflectionClass($type); $obj = $reflection_obj->newInstanceArgs($parameter); // return the created object return $obj; } } Expected result: ---------------- The script should successfully create an object when for() or foreach()-loop is used. Actual result: -------------- The script works only with for()-loop. When the foreach look is used, the following error message is shown. [error] [client 127.0.0.1] PHP Warning: Invocation of test_obj2's constructor failed in /.../test.php on line 183, referer: http://127.0.0.1:8080/ ... The line references to "$obj = $reflection_obj->newInstanceArgs($parameter);" at the get_object_NOK.() function. ------------------------------------------------------------------------ -- Edit this bug report at http://bugs.php.net/bug.php?id=51284&edit=1