PHP对象字面量

69

在PHP中,我可以很容易地指定数组字面量:

array(
    array("name" => "John", "hobby" => "hiking"),
    array("name" => "Jane", "hobby" => "dancing"),
    ...
)

但是如果我想要一个对象数组怎么办?在PHP中如何指定对象字面量? 例如,在JavaScript中,它可能是这样的:

但是如果我想要一个对象数组怎么办?在PHP中如何指定对象字面量? 例如,在JavaScript中,它可能是这样的:

[
    {name: "John", hobby: "hiking"},
    {name: "Jane", hobby: "dancing"}
]

5
PHP 中没有对象字面量。 - BoltClock
1
@ŠimeVidas,我不理解你的评论。JS对象是关联数组,但PHP关联数组不是对象。此外,PHP不是ECMAScript语言,也不是JS。 - Dima Zorin
@DmitryZorin 我明白了。我以为 PHP 的关联数组 就像 JavaScript 中的对象一样是对象。 - Šime Vidas
@ŠimeVidas 我明白你的意思,但你必须理解两种不同语言的解释方式是非常不同的。 - GriffLab
3
@ŠimeVidas我认为TMS是在JavaScript中展示如何操作,那么问题是“我怎样在PHP中做到同样的效果?” - Stewart
可能是Does PHP feature short hand syntax for objects?的重复问题。 - faintsignal
10个回答

98

正如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;

13
请注意,对象始终是按引用传递的,而数组不是。 因此,更改对象属性会在对象分配的所有位置都改变它。但对于数组来说并非如此,它们保持独立。 - Gregory Cosmo Haun
1
@GregoryCosmoHaun 对象不是通过引用传递的,而是通过称为对象标识符的数值传递的。这允许对象访问器找到实际的对象。 - Rain
@Rain 有什么区别吗?指向特定对象的“对象标识符”是对该对象的引用,不是吗? - Stack Underflow
1
@Stack-Underflow 你可以在这里看到这些技术的不同之处 https://3v4l.org/hkOcA - Rain
1
@Rain,你提供的示例有一个错别字,这导致了你想要展示的内容不够清晰。这是一个已经修正过的版本:https://3v4l.org/njjm6。 - David P. Caldwell
@DavidP.Caldwell,@Rain 该示例清楚地展示了对象是通过引用传递的。你将按引用传递对象与按引用传递变量的引用混淆了。这在几乎所有其他语言中也是如此,将引用称为“标识符”可能是 PHP 的一个怪癖,但这并不改变它是按引用传递的事实。 - Remember Monica

69
从PHP 5.4开始,您还可以使用短数组语法:
$json = [
    (object) ['name' => 'John', 'hobby' => 'hiking'],
    (object) ['name' => 'Jane', 'hobby' => 'dancing'],
];

3
太好了,这使得脚本更加简洁。 - David V

16

正如其他人所指出的那样,PHP中没有对象字面量,但是您可以通过将数组转换为对象来"模拟"它。

使用PHP 5.4,这甚至更加简洁,因为数组可以用方括号声明。例如:

$obj = (object)[
    "foo" => "bar",
    "bar" => "foo",
];

这将为您提供一个具有“foo”和“bar”属性的对象。但是,我认为这与使用关联数组没有太大优势。这只是一种语法上的区别。

考虑接纳您所使用的所有语言的独特性和“风味”。在JavaScript中,对象字面量随处可见。在PHP中,关联数组在功能上与JavaScript对象字面量相同,易于创建,并且被其他PHP程序员广泛理解。我认为你最好接受这种“风味”,而不是试图让它感觉像JavaScript的对象字面量语法。


4

虽然在一个层级中将对象进行类型转换(casting)是可行的,但它无法深入到更深的层次。换句话说,如果我们想要每个层级上的对象,我们需要像下面这样进行处理:

$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]
]));

这可以确保它是在最深层级上的一个对象。

回答klewis的问题,您可以像这样访问它:

echo $foods->vegetables->broccoli;

这个例子会输出数字5。


好的解决方案,您能否提供一个简单的示例,演示在echo语句中引用西兰花值的第二个选项? - klewis
1
<?php $foods = json_decode(json_encode([ "fruits" => ["apple" => 1, "banana" => 2, "cherry" => 3], "vegetables" => ["asparagus" => 4, "broccoli" => 5, "carrot" => 6] ])); echo $foods->vegetables->broccoli; ?>应输出数字5 - Dave Lampert
迄今为止,这个帖子中最好的答案,适用于来自JavaScript背景并且想要单层或深层方法的人。 - klewis

4

3
如果能够运行就太酷了,但是 stdClass 没有定义 __set_state 方法。 - Shad

2

我用JavaScript风格的对象字面量在PHP中的方法如下:

首先,我创建一个关联数组,就像这样:

$test = array(
  'name' => "test",
  'exists' => true
);

然后我可以轻松地将它变成一个对象,像这样:
$test = (object)$test;

现在你可以进行测试:
echo gettype($test); // "object"
echo $test->name; // "test"

0
在PHP中,您必须先创建一个实例才能使用类。当然,您可以稍后将实例放入数组中。

0
如果你想要在对象字面量模式中“像JavaScript一样”定义模块,你可以这样做:
$object = (object) [
    'config' => (object) [
        'username' => 'Rob Bennet',
        'email' => 'rob@madebyhoundstooth.com'
    ],

    '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' => 'wolverine@xmen.com'
]);

在这种模块化情况下,我通常选择外观模式,我喜欢这样编写我的调用:
Module::action()->item;

或者

Post::get()->title;

这些模式都不容易进行测试(有时甚至是不可能的)。但这只是概念证明。从技术上讲,“没有”PHP中的对象字面量,但如果您习惯于JavaScript语法(我比PHP更熟悉),则可以模拟并执行此操作。正如您所看到的,在PHP中,这样做要比在JavaScript中麻烦得多。


0
如果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 );

-1

简单解决方案

$obj = json_decode('{"ape":"kwyjibo"}');
echo $obj->ape;

[output:]
kwyjibo

然后您可以将其封装到一个函数中并返回您的字面对象

$obj = literal_object(['key1','val1','key2','val2']);

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接