ご存知のように、JavaScriptで匿名オブジェクトを作成するのは、次のコードのように簡単です。
var object = {
p : "value",
p1 : [ "john", "johnny" ]
};
alert(object.p1[1]);
出力:
an alert is raised with value "johnny"
これと同じ手法をPHPに適用できますか?PHPで匿名オブジェクトを作成できますか?
ご存知のように、JavaScriptで匿名オブジェクトを作成するのは、次のコードのように簡単です。
var object = {
p : "value",
p1 : [ "john", "johnny" ]
};
alert(object.p1[1]);
出力:
an alert is raised with value "johnny"
これと同じ手法をPHPに適用できますか?PHPで匿名オブジェクトを作成できますか?
回答:
もう何年か経ちますが、情報を最新の状態に保つ必要があると思います。
PHP 7以降、匿名クラスを作成できるようになったため、次のようなことができます。
<?php
class Foo {}
$child = new class extends Foo {};
var_dump($child instanceof Foo); // true
?>
しかし、JavaScriptにどのように実装されるかはわかりません。そのため、JavaScriptとPHPの匿名クラスにはいくつかの違いがあるかもしれません。
オブジェクトについて話すとき、「匿名」は正しい用語ではありません。「匿名型のオブジェクト、これはPHPには当てはまりません。
PHPのすべてのオブジェクトにはクラスがあります。「デフォルト」クラスはstdClass
であり、この方法でオブジェクトを作成できます。
$obj = new stdClass;
$obj->aProperty = 'value';
さらに便利な構文として、配列をオブジェクトにキャストすることもできます。
$obj = (object)array('aProperty' => 'value');
print_r($obj);
ただし、配列をオブジェクトにキャストすると、有効なPHP変数名ではない配列キーに対して「興味深い」結果が得られる可能性があることに注意してください。たとえば、ここでは、キーが数字で始まる場合にどうなるかを示す私の答えを示します。
はい、可能です!この単純なPHP匿名オブジェクトクラスを使用します。使い方:
// define by passing in constructor
$anonim_obj = new AnObj(array(
"foo" => function() { echo "foo"; },
"bar" => function($bar) { echo $bar; }
));
$anonim_obj->foo(); // prints "foo"
$anonim_obj->bar("hello, world"); // prints "hello, world"
// define at runtime
$anonim_obj->zoo = function() { echo "zoo"; };
$anonim_obj->zoo(); // prints "zoo"
// mimic self
$anonim_obj->prop = "abc";
$anonim_obj->propMethod = function() use($anonim_obj) {
echo $anonim_obj->prop;
};
$anonim_obj->propMethod(); // prints "abc"
もちろん、このオブジェクトはAnObj
クラスのインスタンスであるため、実際には匿名ではありませんが、JavaScriptのように、その場でメソッドを定義できます。
最近まで、これはオブジェクトをその場で作成する方法でした。
$someObj = json_decode("{}");
次に:
$someObj->someProperty = someValue;
しかし、今私は行きます:
$someObj = (object)[];
次に、以前のように:
$someObj->someProperty = someValue;
もちろん、すでにプロパティと値がわかっている場合は、前述のように内部に設定できます。
$someObj = (object)['prop1' => 'value1','prop2' => 'value2'];
注意:これが動作するPHPのバージョンがわからないので、注意する必要があります。しかし、私は最初のアプローチ(構築時に設定するプロパティがない場合も短い)はjson_encode / json_decodeを持つすべてのバージョンで機能するはずだと思います
JavaScriptを模倣したい場合は、クラスを作成してObject
、同じ動作を得ることができます。もちろん、これはもはや匿名ではありませんが、機能します。
<?php
class Object {
function __construct( ) {
$n = func_num_args( ) ;
for ( $i = 0 ; $i < $n ; $i += 2 ) {
$this->{func_get_arg($i)} = func_get_arg($i + 1) ;
}
}
}
$o = new Object(
'aProperty', 'value',
'anotherProperty', array('element 1', 'element 2')) ;
echo $o->anotherProperty[1];
?>
要素2が出力されます。これは、PHP:Classes and Objectsに関するコメントから盗まれました。
匿名クラスのサポートはPHP 7.0以降で利用可能であり、質問で提供されているJavaScriptの例に最も近いものです。
<?php
$object = new class {
var $p = "value";
var $p1 = ["john", "johnny"];
};
echo $object->p1[1];
プロパティの可視性宣言は省略できません(私はvar
それがpublic
。より短いので使用しただけです)。
JavaScriptと同様に、クラスのメソッドも定義できます。
<?php
$object = new class {
var $p = "value";
var $p1 = ["john", "johnny"];
function foo() {return $this->p;}
};
echo $object->foo();
PHPドキュメントから、さらにいくつかの例:
<?php
$obj1 = new \stdClass; // Instantiate stdClass object
$obj2 = new class{}; // Instantiate anonymous class
$obj3 = (object)[]; // Cast empty array to object
var_dump($obj1); // object(stdClass)#1 (0) {}
var_dump($obj2); // object(class@anonymous)#2 (0) {}
var_dump($obj3); // object(stdClass)#3 (0) {}
?>
$ obj1と$ obj3は同じタイプですが、$ obj1!== $ obj3です。また、3つすべてがjson_encode()を単純なJSオブジェクト{}に変換します。
<?php
echo json_encode([
new \stdClass,
new class{},
(object)[],
]);
?>
出力:
[{},{},{}]
プロパティに値を設定していないときに、未定義のプロパティの警告を受け取らずに、動的プロパティを持つオブジェクト(JavaScriptなど)を作成する場合
class stdClass {
public function __construct(array $arguments = array()) {
if (!empty($arguments)) {
foreach ($arguments as $property => $argument) {
if(is_numeric($property)):
$this->{$argument} = null;
else:
$this->{$property} = $argument;
endif;
}
}
}
public function __call($method, $arguments) {
$arguments = array_merge(array("stdObject" => $this), $arguments); // Note: method argument 0 will always referred to the main class ($this).
if (isset($this->{$method}) && is_callable($this->{$method})) {
return call_user_func_array($this->{$method}, $arguments);
} else {
throw new Exception("Fatal error: Call to undefined method stdObject::{$method}()");
}
}
public function __get($name){
if(property_exists($this, $name)):
return $this->{$name};
else:
return $this->{$name} = null;
endif;
}
public function __set($name, $value) {
$this->{$name} = $value;
}
}
$obj1 = new stdClass(['property1','property2'=>'value']); //assign default property
echo $obj1->property1;//null
echo $obj1->property2;//value
$obj2 = new stdClass();//without properties set
echo $obj2->property1;//null
これと同じテクニックをPHPの場合にも適用できますか?
いいえ-JavaScriptはプロトタイプ/オブジェクトの直接宣言を使用するため-PHP(および他の多くのオブジェクト指向言語)では、オブジェクトはクラスからのみ作成できます。
だから問題は-匿名クラスを作成できますか?
もう一度答えはノーです-それを参照することができずにクラスをどのようにインスタンス化しますか?
Object var = new Object() { ... };
-C ++:class { ... } var;
再帰的なオブジェクトが必要な場合:
$o = (object) array(
'foo' => (object) array(
'sub' => '...'
)
);
echo $o->foo->sub;