[解決済み] PHP - オーバーロードされたプロパティの間接的な変更
質問
この質問は何度かされているようですが、どれも回避策についてまともな答えがないようです。もしかしたら、私のような特殊なケースに対応するものがあるかもしれません。
マジックメソッドを使用するマッパークラスを作成しています。
__get()
を使用して、他のオブジェクトを遅延ロードします。以下のような感じです。
public function __get ( $index )
{
if ( isset ($this->vars[$index]) )
{
return $this->vars[$index];
}
// $index = 'role';
$obj = $this->createNewObject ( $index );
return $obj;
}
私のコードでは、そうしています。
$user = createObject('user');
$user->role->rolename;
これは今のところうまくいっています。その
User
オブジェクトは 'role' という名前のプロパティを持っていないので、マジックである
__get()
メソッドを使用してそのオブジェクトを作成し、そのプロパティを 'role' オブジェクトから返します。
しかし、私は'rolename'を変更しようとしたとき。
$user = createUser();
$user->role->rolename = 'Test';
すると、以下のようなエラーが発生します。
お知らせです。オーバーロードされたプロパティの間接的な変更は効果なし
これがPHPのバグなのか、それとも期待された動作なのかは分かりませんが、いずれにせよ、私の望むような動作はしません。これは私にとっては本当にショーストッパーです...。なぜなら、一体どうやって遅延ロードされたオブジェクトのプロパティを変更することができるのでしょうか?
EDIT
実際の問題は、複数のオブジェクトを含む配列を返したときだけ発生するようです。
この問題を再現するコードの例を追加しました。
本当に「エラー」を確認するには、PHP環境でこれを実行する必要があります。しかし、ここでは本当に面白いことが起こっているのです。
あるオブジェクトのプロパティを変更しようとすると、「cant change overloaded property」というメッセージが表示されます。しかし、その後にプロパティをechoすると、実際に値が変更されたことがわかります。本当に奇妙です...
どうすればいいですか?
いいものを見せてもらった
走る
class Sample extends Creator {
}
$a = new Sample ();
$a->role->rolename = 'test';
echo $a->role->rolename , PHP_EOL;
$a->role->rolename->am->love->php = 'w00';
echo $a->role->rolename , PHP_EOL;
echo $a->role->rolename->am->love->php , PHP_EOL;
出力
test
test
w00
使用クラス
abstract class Creator {
public function __get($name) {
if (! isset ( $this->{$name} )) {
$this->{$name} = new Value ( $name, null );
}
return $this->{$name};
}
public function __set($name, $value) {
$this->{$name} = new Value ( $name, $value );
}
}
class Value extends Creator {
private $name;
private $value;
function __construct($name, $value) {
$this->name = $name;
$this->value = $value;
}
function __toString()
{
return (string) $this->value ;
}
}
Edit : ご要望の多かった新しい配列のサポート
class Sample extends Creator {
}
$a = new Sample ();
$a->role = array (
"A",
"B",
"C"
);
$a->role[0]->nice = "OK" ;
print ($a->role[0]->nice . PHP_EOL);
$a->role[1]->nice->ok = array("foo","bar","die");
print ($a->role[1]->nice->ok[2] . PHP_EOL);
$a->role[2]->nice->raw = new stdClass();
$a->role[2]->nice->raw->name = "baba" ;
print ($a->role[2]->nice->raw->name. PHP_EOL);
出力
Ok die baba
モディファイドクラス
abstract class Creator {
public function __get($name) {
if (! isset ( $this->{$name} )) {
$this->{$name} = new Value ( $name, null );
}
return $this->{$name};
}
public function __set($name, $value) {
if (is_array ( $value )) {
array_walk ( $value, function (&$item, $key) {
$item = new Value ( $key, $item );
} );
}
$this->{$name} = $value;
}
}
class Value {
private $name ;
function __construct($name, $value) {
$this->{$name} = $value;
$this->name = $value ;
}
public function __get($name) {
if (! isset ( $this->{$name} )) {
$this->{$name} = new Value ( $name, null );
}
if ($name == $this->name) {
return $this->value;
}
return $this->{$name};
}
public function __set($name, $value) {
if (is_array ( $value )) {
array_walk ( $value, function (&$item, $key) {
$item = new Value ( $key, $item );
} );
}
$this->{$name} = $value;
}
public function __toString() {
return (string) $this->name ;
}
}
関連
-
[解決済み】ディレクトリ内のファイル数を数える PHP
-
[解決済み】SSLピア証明書またはSSHリモートキーがOKでなかった
-
[解決済み】Fatal error: mysqli_result 型のオブジェクトは使用できません [終了] 。
-
[解決済み] PHPで配列から要素を削除する
-
[解決済み] PHPでSQLインジェクションを防ぐにはどうしたらいいですか?
-
[解決済み] PHPでHTML/XMLをパースして処理する方法とは?
-
[解決済み] PHPのエラーを表示させるにはどうしたらいいですか?
-
[解決済み] PHPのstartWith()関数とendsWith()関数
-
[解決済み】PHPの'foreach'は実際どのように動作するのですか?
-
[解決済み] リファレンス - このシンボルはPHPで何を意味するのですか?
最新
-
nginxです。[emerg] 0.0.0.0:80 への bind() に失敗しました (98: アドレスは既に使用中です)
-
htmlページでギリシャ文字を使うには
-
ピュアhtml+cssでの要素読み込み効果
-
純粋なhtml + cssで五輪を実現するサンプルコード
-
ナビゲーションバー・ドロップダウンメニューのHTML+CSSサンプルコード
-
タイピング効果を実現するピュアhtml+css
-
htmlの選択ボックスのプレースホルダー作成に関する質問
-
html css3 伸縮しない 画像表示効果
-
トップナビゲーションバーメニュー作成用HTML+CSS
-
html+css 実装 サイバーパンク風ボタン
おすすめ
-
[解決済み] PHP & MySQL: mysqli_num_rows() expects parameter 1 to be mysqli_result, boolean given [重複] PHP & MySQL: mysqli_num_rows() expects parameter 1 to be mysqli_result, boolean given.
-
[解決済み] 整形されていない数値が発生しました。
-
[解決済み】Apache + PHPで「ヘッダの前にスクリプトの出力が終了する」件
-
[解決済み】 libapache2-mod-php7 パッケージが見つからない。
-
[解決済み】子テーマのCSSが親テーマをオーバーライドしない
-
[解決済み】警告。数値でない値に遭遇しました
-
[解決済み】/var/www/htmlとは何ですか?[クローズド]
-
[解決済み] PHP と mod_fcgid: handle_request_ipc 関数で ap_pass_brigade が失敗する。
-
[解決済み】警告: file_get_contents(): https:// ラッパーがサーバー構成ですべて無効になっています。
-
[解決済み] PHPの配列を別の配列にコピーする関数はありますか?