Bug #51284 [NEW]: foreach distroys objects in array

From: Date: Fri, 12 Mar 2010 12:29:45 +0000
Subject: Bug #51284 [NEW]: foreach distroys objects in array
Groups: php.bugs 
Request: Send a blank email to php-bugs+get-148562@lists.php.net to get a copy of this message
From:             
Operating system: MacOSX, Linux, ...
PHP version:      Irrelevant
Package:          Class/Object related
Bug Type:         Bug
Bug description:foreach distroys objects in array

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 bug report at http://bugs.php.net/bug.php?id=51284&edit=1
-- 
Try a snapshot (PHP 5.2):            http://bugs.php.net/fix.php?id=51284&r=trysnapshot52
Try a snapshot (PHP 5.3):            http://bugs.php.net/fix.php?id=51284&r=trysnapshot53
Try a snapshot (PHP 6.0):            http://bugs.php.net/fix.php?id=51284&r=trysnapshot60
Fixed in SVN:                        http://bugs.php.net/fix.php?id=51284&r=fixed
Fixed in SVN and need be documented: http://bugs.php.net/fix.php?id=51284&r=needdocs
Fixed in release:                    http://bugs.php.net/fix.php?id=51284&r=alreadyfixed
Need backtrace:                      http://bugs.php.net/fix.php?id=51284&r=needtrace
Need Reproduce Script:               http://bugs.php.net/fix.php?id=51284&r=needscript
Try newer version:                   http://bugs.php.net/fix.php?id=51284&r=oldversion
Not developer issue:                 http://bugs.php.net/fix.php?id=51284&r=support
Expected behavior:                   http://bugs.php.net/fix.php?id=51284&r=notwrong
Not enough info:                     http://bugs.php.net/fix.php?id=51284&r=notenoughinfo
Submitted twice:                     http://bugs.php.net/fix.php?id=51284&r=submittedtwice
register_globals:                    http://bugs.php.net/fix.php?id=51284&r=globals
PHP 4 support discontinued:          http://bugs.php.net/fix.php?id=51284&r=php4
Daylight Savings:                    http://bugs.php.net/fix.php?id=51284&r=dst
IIS Stability:                       http://bugs.php.net/fix.php?id=51284&r=isapi
Install GNU Sed:                     http://bugs.php.net/fix.php?id=51284&r=gnused
Floating point limitations:          http://bugs.php.net/fix.php?id=51284&r=float
No Zend Extensions:                  http://bugs.php.net/fix.php?id=51284&r=nozend
MySQL Configuration Error:           http://bugs.php.net/fix.php?id=51284&r=mysqlcfg



Thread (7 messages)

« previous php.bugs (#148562) next »