如何在PHP> = 5.3严格模式下向对象添加属性而不会产生错误


81

这必须很简单,但是我似乎找不到答案。

我有一个$foo没有属性的通用stdClass对象。我想向其中添加一个$bar尚未定义的新属性。如果我这样做:

$foo = new StdClass();
$foo->bar = '1234';

PHP在严格模式下抱怨。

(在类声明之外)将属性添加到已实例化的对象的正确方法是什么?

注意:我希望该解决方案能够与类型为stdClass的通用PHP对象一起使用。

关于这个问题的一些背景。我正在解码json字符串,它是json对象的数组。 json_decode()生成StdClass对象的数组。我需要操纵这些对象,并为每个对象添加一个属性。


尝试将TRUE第二个参数传递给json_decode。它会为您提供一个关联数组,而不是对象数组。
火箭Hazmat

1
严格模式下的PHP不会对此抱怨。3v4l.org/kn0hi
hakre 2013年

3
我不知道为什么这已经关闭,因为这是一个完全有效的问题。我现在有一个完全类似的问题。
2014年

Answers:


130

如果绝对必须将属性添加到对象,我相信您可以将其强制转换为数组,添加属性(作为新的数组键),然后将其强制强制转换为对象。stdClass我相信,遇到对象的唯一时间是将数组强制转换为对象时,或者stdClass从头开始创建新对象时(当然,当您遇到json_decode()某些情况时,我真会忘记!)。

代替:

$foo = new StdClass();
$foo->bar = '1234';

您可以:

$foo = array('bar' => '1234');
$foo = (object)$foo;

或者,如果您已经有一个现有的stdClass对象:

$foo = (array)$foo;
$foo['bar'] = '1234';
$foo = (object)$foo;

也作为1班轮:

$foo = (object) array_merge( (array)$foo, array( 'bar' => '1234' ) );

1
当解码json时,遇到StdClass的地方很常见。

1
@Ray我很遗憾地摇了摇头,我没想到提起那件事。=)
Crontab

3
您的解决方案有效,但是却伤害了我的OO心脏:)希望使用某种类型的浮华反射kung foo或类似的东西...希望将问题延长一点,并希望有一些鲜为人知的PHP魔术。

1
@Ray hehehe ...我希望我能给您带来更多优雅的感觉。顺便说一句,显式设置error_reporting(E_STRICT);PHP 5.3.15-1~dotdeb.0 with Suhosin-Patch,尝试在stdClass对象上设置不存在的属性时,我没有收到任何错误或通知。您正在使用哪个版本的PHP?
Crontab

哈,将近三年后,由于某种原因,我得到了毫无解释的无记名投票。谢谢。
Crontab

111

像这样做:

$foo = new stdClass();
$foo->{"bar"} = '1234';

现在尝试:

echo $foo->bar; // should display 1234

2
作为魅力。这应该是公认的解决方案。
Tarrakis

如何使用此语法将属性添加到对象上的字段?

Laravel中的“试图分配非对象的属性”错误
Rejaul

甚至“ bar”字符串也可以位于变量中:$ foo-> {$ any_variable} ='1234';
撒拉族(Salar)

这绝对应该是公认的答案,因为它可以使对象引用保持完整(在我看来,这很关键)。
Johan Fredrik Varen

11

如果要编辑解码的JSON,请尝试将其作为关联数组而不是对象数组获取。

$data = json_decode($json, TRUE);

2

我总是用这种方式:

$foo = (object)null; //create an empty object
$foo->bar = "12345";

echo $foo->bar; //12345

1

您应该使用魔术方法__Set和__get。简单的例子:

class Foo
{
    //This array stores your properties
private $content = array();

public function __set($key, $value)
{
            //Perform data validation here before inserting data
    $this->content[$key] = $value;
    return $this;
}

public function __get($value)
{       //You might want to check that the data exists here
    return $this->$content[$value];
}

}

当然,不要像这样使用此示例:完全没有安全性:)

编辑:看到您的评论,这里可能是基于反射和装饰的替代方案:

 class Foo
 {
private $content = array();
private $stdInstance;

public function __construct($stdInstance)
{
    $this->stdInstance = $stdInstance;
}

public function __set($key, $value)
{
    //Reflection for the stdClass object
    $ref = new ReflectionClass($this->stdInstance);
    //Fetch the props of the object

    $props = $ref->getProperties();

    if (in_array($key, $props)) {
        $this->stdInstance->$key = $value;
    } else {
        $this->content[$key] = $value;
    }
    return $this;
}

public function __get($value)
{
    //Search first your array as it is faster than using reflection
    if (array_key_exists($value, $this->content))
    {
        return $this->content[$value];
    } else {
        $ref = new ReflectionClass($this->stdInstance);

        //Fetch the props of the object
        $props = $ref->getProperties();

        if (in_array($value, $props)) {

        return $this->stdInstance->$value;
    } else {
        throw new \Exception('No prop in here...');
    }
}
 }
}

PS:我没有测试我的代码,只是一般的想法...


3
本杰明,我想使用PHP的通用对象类:StdClass。我无法修改此类。

Ray,我用适合您需求的解决方案更新了我的答案,但是很沉重:-/
Benjamin Dubois 2012年

1

我不知道它的最新版本的php,但这可行。我正在使用php 5.6

    <?php
    class Person
    {
       public $name;

       public function save()
       {
          print_r($this);
       }
    }

   $p = new Person;
   $p->name = "Ganga";
   $p->age = 23;

   $p->save();

这就是结果。save方法实际上获得了新属性

    Person Object
    (
       [name] => Ganga
       [age] => 23
    )

我对php版本的代码进行了几次测试,结果显示它仅适用于php 5及更高版本。php5以下的任何版本都会引发错误。
大树

-6

是的,可以向PHP对象动态添加属性。

当从javascript接收部分对象时,这很有用。

JAVASCRIPT端:

var myObject = { name = "myName" };
$.ajax({ type: "POST", url: "index.php",
    data: myObject, dataType: "json",
    contentType: "application/json;charset=utf-8"
}).success(function(datareceived){
    if(datareceived.id >= 0 ) { /* the id property has dynamically added on server side via PHP */ }
});

PHP方面:

$requestString = file_get_contents('php://input');
$myObject = json_decode($requestString); // same object as was sent in the ajax call
$myObject->id = 30; // This will dynamicaly add the id property to the myObject object

或者只是从javascript发送一个虚拟属性,您将填写PHP。


我认为从JS发送虚拟属性并在PHP端进行填充是最简单的智能解决方案。谢谢!
Adrian P.

8
o_O O_o o_O O_o
theflowersoftime
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.