PHPでは、配列リテラルを非常に簡単に指定できます。
array(
array("name" => "John", "hobby" => "hiking"),
array("name" => "Jane", "hobby" => "dancing"),
...
)
しかし、オブジェクトの配列が必要な場合はどうなりますか? PHPでオブジェクトリテラルを指定するにはどうすればよいですか?つまりjavascriptの場合:
[
{name: "John", hobby: "hiking"},
{name: "Jane", hobby: "dancing"}
]
BoltClockが述べたように、PHPにはオブジェクトリテラルはありませんが、配列をオブジェクトに型キャストするだけでこれを行うことができます。
$testArray = array(
(object)array("name" => "John", "hobby" => "hiking"),
(object)array("name" => "Jane", "hobby" => "dancing")
);
echo "Person 1 Name: ".$testArray[0]->name;
echo "Person 2 Hobby: ".$testArray[1]->hobby;
PHP 5.4の時点で、短い配列構文を使用することもできます。
$json = [
(object) ['name' => 'John', 'hobby' => 'hiking'],
(object) ['name' => 'Jane', 'hobby' => 'dancing'],
];
他の人が指摘したように、PHPにはオブジェクトリテラルはありませんが、オブジェクトに配列をキャストすることでそれを「偽造」できます。
PHP 5.4では、 配列は角括弧で宣言できます なので、これはさらに簡潔です。たとえば:
$obj = (object)[
"foo" => "bar",
"bar" => "foo",
];
これにより、「foo」および「bar」プロパティを持つオブジェクトが得られます。しかし、連想配列を使用するよりも、これが実際に大きな利点を提供するとは思わない。これは単なる構文の違いです。
使用するすべての言語の独自性と「フレーバー」を採用することを検討してください。 JavaScriptでは、オブジェクトリテラルはいたるところにあります。 PHPでは、連想配列は機能的にJavaScriptオブジェクトリテラルと同じであり、作成が容易であり、他のPHPプログラマーによってよく理解されています。 JavaScriptのオブジェクトリテラル構文のように感じさせようとしています。
別の方法は、 __set_state()
magicメソッドを使用することです。
$object = stdClass::__set_state (array (
'height' => -10924,
'color' => 'purple',
'happy' => false,
'video-yt' => 'AgcnU74Ld8Q'
));
(オブジェクト)としてのキャストは、単一の階層レベルでは問題なく機能しますが、深くは行きません。つまり、すべてのレベルでオブジェクトが必要な場合は、次のようなことをする必要があります。
$foods = (object)[
"fruits" => (object)["Apple" => 1, "banana" => 2, "cherry" => 3],
"vegetables" => (object)["asparagus" => 4, "broccoli" => 5, "carrot" => 6]
];
ただし、オブジェクトとして複数のキャストを行う代わりに、次のようにjson_encodeとjson_decodeで全体をラップできます。
$foods = json_decode(json_encode([
"fruits" => ["Apple" => 1, "banana" => 2, "cherry" => 3],
"vegetables" => ["asparagus" => 4, "broccoli" => 5, "carrot" => 6]
]));
これにより、最深レベルのオブジェクトになります。
PHPのJavaScriptスタイルオブジェクトリテラルの私の方法は次のとおりです。
まず、次のような連想配列を作成します。
$test = array(
'name' => "test",
'exists' => true
);
それから、私は簡単にそれをこのようなオブジェクトにします:
$test = (object)$test;
これでテストできます:
echo gettype($test); // "object"
echo $test->name; // "test"
「JavaScriptのような」オブジェクトリテラルパターンでモジュールを定義する場合は、次のようにできます。
$object = (object) [
'config' => (object) [
'username' => 'Rob Bennet',
'email' => '[email protected]'
],
'hello' => function() use(&$object) {
return "Hello " . $object->config->username . ". ";
},
'emailDisplay' => function() use(&$object) {
return "Your email address is " . $object->config->email;
},
'init' => function($options) use(&$object) {
$object->config = $options;
$doUsername = $object->hello;
$doEmail = $object->emailDisplay;
return $doUsername() . $doEmail();
}
];
$sayMyInfo = $object->init;
echo $sayMyInfo((object) [
'username' => 'Logan',
'email' => '[email protected]'
]);
このタイプのモジュラーシナリオでは、通常 facade pattern を選択します。このように呼び出しを記述するのが好きです。
Module::action()->item;
または
Post::get()->title;
これらのパターンのどちらも、テストを簡単に(または場合によっては)可能にしません。しかし、これは単なる概念実証です。技術的には、PHPにはオブジェクトリテラルはありませんが、JavaScript構文(私はPHPよりも優れています)に慣れているなら、それを偽造してこれを行うことができます。ご覧のとおり、PHPではJavaScriptよりもはるかに厄介です。
PHPでは、クラスを使用する前にインスタンスを作成します。もちろん、後でインスタンスを配列に入れることができます。
json_decode(json_encode( $array ))
が適切でない場合、これらのような類似の関数を使用できます。どちらが速いかわかりません。
function deep_cast_object( $o ){
return deep_cast_object_ref( $o );
}
function deep_cast_object_ref( & $o ){
if( is_array( $o ))
$o = (object)$o;
if( is_object( $o ))
foreach( $o as & $v )
deep_cast_object_ref( $v );
return $o;
}
$obj = deep_cast_object(array(
'Fractal' => array(
'of' => array(
'bad' => 'design',
),
),
));
var_dump( $obj );