【问题标题】:PHP object literalPHP 对象字面量
【发布时间】:2012-03-27 13:00:45
【问题描述】:

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

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

但是如果我想要对象数组怎么办?如何在 PHP 中指定对象文字? IE。在 javascript 中它会是:

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

【问题讨论】:

  • PHP 中没有对象字面量。
  • @ŠimeVidas,我不明白你的评论。 JS 对象是关联数组,而 PHP 关联数组不是对象。另外 PHP 不是 ECMAScript 语言,PHP 甚至不是 JS。
  • @DmitryZorin 我明白了。我认为 PHP 关联数组 对象(就像在 JavaScript 中一样)。
  • @ŠimeVidas 我明白你在说什么,但你必须明白这两种不同的语言是如何被解释的,这是非常不同的。
  • @ŠimeVidas 我认为 TMS 展示了如何在 JavaScript 中实现这一点。所以问题是“我如何在 PHP 中做同样的事情?”

标签: php object literals object-literal


【解决方案1】:

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

【讨论】:

  • 请注意,对象总是通过引用传递,数组不是。因此,更改对象的属性会在分配对象的任何地方更改它。数组不是这种情况;他们保持独立。
  • @GregoryCosmoHaun 对象不通过引用传递。它们由称为对象标识符的数值传递。这允许对象访问器找到实际的对象。
  • @Rain 有什么区别?引用特定对象的“对象标识符”是对该对象的引用,不是吗?
  • @Stack-Underflow 你可以在这里看到这些技术的不同3v4l.org/hkOcA
【解决方案2】:

从 PHP 5.4 开始,您还可以使用短数组语法:

$json = [
    (object) ['name' => 'John', 'hobby' => 'hiking'],
    (object) ['name' => 'Jane', 'hobby' => 'dancing'],
];

【讨论】:

  • 非常好,这使得脚本更简洁
【解决方案3】:

正如其他人所指出的,PHP 中没有对象字面量,但您可以通过将数组转换为对象来“伪造”它。

使用 PHP 5.4,这更加简洁,因为arrays can be declared with square brackets。例如:

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

这会给你一个具有“foo”和“bar”属性的对象。但是,我认为这并没有比使用关联数组提供太多优势。这只是语法差异。

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

【讨论】:

    【解决方案4】:

    另一种方法是使用__set_state() 魔术方法:

    $object = stdClass::__set_state (array (
        'height'   => -10924,
        'color'    => 'purple',
        'happy'    => false,
        'video-yt' => 'AgcnU74Ld8Q'
    ));
    

    Some more on the __set_state() method, where is it coming from and how is it supposed to be used.

    【讨论】:

    • -1,如果它有效,那就太酷了。但是,stdClass 没有定义的 __set_state 方法。
    【解决方案5】:

    虽然转换为(对象)在单个层次级别上可以正常工作,但它并不深入。换句话说,如果我们想要每个级别的对象,我们必须执行以下操作:

    $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 语句中引用 broccoli 的值时的第二个选项?
    • <?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
    • 到目前为止,这个线程上的最佳答案是来自 javascript 背景并想要单层或深层方法。
    【解决方案6】:

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

    首先我创建一个这样的关联数组:

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

    然后我很容易地把它变成这样的对象:

    $test = (object)$test;
    

    现在你可以测试它了:

    echo gettype($test); // "object"
    echo $test->name; // "test"
    

    【讨论】:

      【解决方案7】:

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

      【讨论】:

        【解决方案8】:

        如果你想在对象字面量模式中“像 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'
        ]);
        

        在这种类型的模块化场景中,我通常选择facade pattern,我只是喜欢这样写我的调用:

        Module::action()->item;
        

        Post::get()->title;
        

        这些模式都不能让测试变得容易(有时甚至可能)。但这只是概念证明。从技术上讲,“不”在 PHP 中没有 Object Literal,但如果您习惯 JavaScript 语法(我比 PHP 更习惯),您可以伪造它并执行此操作。如您所见,PHP 比 JavaScript 复杂得多。

        【讨论】:

          【解决方案9】:

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

          【讨论】:

            【解决方案10】:

            简单的解决方案

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

            然后你可以将它包装成一个函数并返回你的文字对象

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

            【讨论】:

              猜你喜欢
              • 2017-01-09
              • 2013-04-22
              • 2014-02-26
              • 2015-12-20
              • 2016-08-23
              • 2012-03-01
              • 2021-08-24
              • 2010-11-09
              • 2015-03-12
              相关资源
              最近更新 更多