エラーを生成せずにPHP> = 5.3strictモードでオブジェクトにプロパティを追加する方法


82

これは単純なことですが、答えが見つからないようです。

$fooプロパティのない汎用stdClassオブジェクトがあります。$barまだ定義されていない新しいプロパティを追加したいと思います。私がこれを行う場合:

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

strictモードのPHPは文句を言います。

すでにインスタンス化されているオブジェクトにプロパティを追加するための適切な方法(クラス宣言以外)は何ですか?

注:ソリューションがstdClass型の汎用PHPオブジェクトで機能するようにしたい。

この問題に関する少しの背景。jsonオブジェクトの配列であるjson文字列をデコードしています。 json_decode()StdClassオブジェクトの配列を生成します。これらのオブジェクトを操作して、それぞれにプロパティを追加する必要があります。


TRUE2番目のパラメータとしてに渡してみてくださいjson_decode。オブジェクトの配列ではなく、連想配列が提供されます。
ロケット危険物2012

1
strictモードのPHPはそれについて文句を言いません。3v4l.org/kn0hi
hakre

3
これは完全に有効な質問であるため、なぜこれが閉じられたのかわかりません。私は今、まったく同じような質問があります。
スティーブン

回答:


131

どうしてもプロパティをオブジェクトに追加する必要がある場合は、それを配列としてキャストし、プロパティを(新しい配列キーとして)追加してから、オブジェクトとしてキャストし直すことができると思います。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
StdClassに遭遇する場所の1つは、jsonをデコードするときです。これはかなり一般的です。
レイ

1
@Ray私はそれについて言及することを考えていなかった悲しみに頭を振っています。=)
Crontab 2012

3
あなたの解決策は機能しますが、それは私のOOの心を傷つけます:)ある種の派手な反射カンフーか何かを望んでいました...質問をもう少し開いたままにして、あまり知られていないPHPの魔法を期待します。
レイ

1
@Ray hehehe ...もっとエレガントなものがあればいいのに。ちなみに、を明示的に設定error_reporting(E_STRICT);するPHP 5.3.15-1~dotdeb.0 with Suhosin-Patchと、stdClassオブジェクトに存在しないプロパティを設定しようとしてもエラーや通知は表示されません。どのバージョンのPHPを使用していますか?
crontab

ハ、ほぼ3年後、私は何らかの理由で説明のないドライブバイの反対票を受け取りました。ありがとうございました。
crontab 2016年

112

このようにしてください:

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

今試してみてください:

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

2
チャームとして機能します。これは受け入れられた解決策であるはずです。
タラキス2018年

この構文を使用して、オブジェクトのフィールドにプロパティを追加するにはどうすればよいですか?
ビッグマネー

Laravelでのエラー「非オブジェクトの割り当てプロパティしようとすると」
Rejaul

「bar」文字列でさえ変数に含めることができます:$ foo-> {$ any_variable} = '1234';
サラー

これは、オブジェクト参照をそのまま維持するため、間違いなく受け入れられる答えになるはずです(私の場合はこれが重要でした)。
Johan FredrikVaren20年

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を使用したいと思います。このクラスを変更することはできません。
レイ

レイ、私はあなたのニーズに対応する解決策で私の答えを更新しました、しかしそれは重いです:-/
ベンジャミンデュボア

1

新しいバージョンのphpかどうかはわかりませんが、これは機能します。私はphp5.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バージョン間でコードに対していくつかのテストを実行しましたが、結果はphp5以降でのみ機能することを示しています。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

または、PHPに入力するjavascriptからダミープロパティを送信するだけです。


JSからダミーのプロパティを送信し、PHP側で入力するのが、最も簡単でスマートなソリューションだと思います。ありがとう!
エイドリアンP.

8
o_O
O_o
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.