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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/11618349/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-25 00:53:06  来源:igfitidea点击:

How to add property to object in PHP >= 5.3 strict mode without generating error

phpclass

提问by Ray

This has to be simple, but I can't seem to find an answer....

这必须很简单,但我似乎无法找到答案....

I have a generic stdClass object $foowith no properties. I want to add a new property $barto it that's not already defined. If I do this:

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

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

PHP in strict mode complains.

严格模式下的 PHP 会抱怨。

What is the proper way (outside of the class declaration) to add a property to an already instantiated object?

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

NOTE: I want the solution to work with the generic PHP object of type stdClass.

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

A little background on this issue. I'm decoding a json string which is an array of json objects. json_decode()generates an array of StdClass object. I need to manipulate these objects and add a property to each one.

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

回答by Crontab

If you absolutely have to add the property to the object, I believe you could cast it as an array, add your property (as a new array key), then cast it back as an object. The only time you run into stdClassobjects (I believe) is when you cast an array as an object or when you create a new stdClassobject from scratch (and of course when you json_decode()something - silly me for forgetting!).

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

Instead of:

代替:

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

You'd do:

你会这样做:

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

Or if you already had an existing stdClass object:

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

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

Also as a 1 liner:

也作为 1 班轮:

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

回答by jmnerd

Do it like this:

像这样做:

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

now try:

现在尝试:

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

回答by Rocket Hazmat

If you want to edit the decoded JSON, try getting it as an associative array instead of an array of objects.

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

$data = json_decode($json, TRUE);

回答by Ragnar

I always use this way:

我总是用这种方式:

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

echo $foo->bar; //12345

回答by Ganga

I don't know whether its the newer version of php, but this works. I'm using php 5.6

我不知道它是否是较新版本的 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();

This is the result. The save method actually gets the new property

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

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

回答by Benjamin Dubois

you should use magic methods __Set and __get. Simple example:

你应该使用魔术方法__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];
}

}

Of course, don't use this example as this : no security at all :)

当然,不要像这样使用这个例子:根本没有安全性:)

EDIT : seen your comments, here could be an alternative based on reflection and a decorator :

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

 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 : I didn't test my code, just the general idea...

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

回答by Adrian Cumpanasu

Yes, is possible to dynamically add properties to a PHP object.

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

This is useful when a partial object is received from javascript.

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

JAVASCRIPT side:

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 side:

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

OR JUST SEND A DUMMY PROPERTY from javascript that you will fill in PHP.

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