更改原始对象时,更改包含PHP的对象中的会话变量

时间:2014-02-19 14:09:12

标签: php session

在某些第三方代码中,我不允许更改,发生了一些奇怪的事情。

他们将一个变量(包含对象的数组)写入会话(不进行序列化),然后使用foreach对原始变量进行迭代(不使用引用)。每当他们更改值时,会话中的相应值也会更改。我能够创建一个具有相同行为的小示例:

  

$ test = array((object)array(“categories”=>“test”));

     

$ _ SESSION ['woot'] = $ test;

     

的print_r($ _ SESSION [ '活泉']);

     

foreach($ test as $ a){

    if (!is_array($a->categories)) $a->categories = array(); 
     

}

     

的print_r($ _ SESSION [ '活泉']);

结果如下:

Array
(
    [0] => stdClass Object
        (
            [categories] => test
        )

)
Array
(
    [0] => stdClass Object
        (
            [categories] => Array
                (
                )

        )

)

我已经注意到,当我序列化和反序列化对象数组时,问题不会发生。

有没有人知道这里发生了什么?这是代码吗?这是不正确的服务器设置吗?在我联系代码开发人员之前,我想了解一点。

其他信息:

  • 我使用的是PHP版本5.3.14
  • 注册全局变量已关闭

此致 Joost的。

2 个答案:

答案 0 :(得分:3)

仅包含对象holds a reference to that object的变量。将对象(对象引用)从一个变量分配给另一个变量不会创建对象的副本,仍然只有一个对象。如果修改该对象,则所有包含对该对象的引用的变量都将看到更改,因为只有一个对象实例。

如果要制作对象的副本,则需要明确clone它。

答案 1 :(得分:1)

在PHP对象中passed by reference,PHP使用copy-on-write

$test = array((object)array("categories" => "test"));
// it is still the same array
$_SESSION['woot'] = $test;
foreach ($test as $a) {
    // You change something in an object, which is passed by reference
    if (!is_array($a->categories)) $a->categories = array();
}

序列化和反序列化会创建新对象

$test = array((object)array("categories" => "test"));
// new array with new objects
$test = unserialize(serialize($test));