【问题标题】:Creating anonymous objects in php在php中创建匿名对象
【发布时间】:2011-09-17 02:03:26
【问题描述】:

众所周知,在 JavaScript 中创建匿名对象很容易,如下面的代码:

var object = { 
    p : "value", 
    p1 : [ "john", "johnny" ]
};

alert(object.p1[1]);

输出:

an alert is raised with value "johnny"

可以在 PHP 中应用同样的技术吗?我们可以在 PHP 中创建匿名对象吗?

【问题讨论】:

  • 注意:这是一个老问题,所以接受的答案已经过时了。所要求的这个特性现在已经被添加到 PHP 7 中。请参阅下面@Rizier123 的答案。
  • @Simba - 感谢您指出。您想在此页面上的 StackOverflow 上发布答案以帮助未来的访问者吗?
  • 我不需要;已经有这个信息的答案(见下文,@Rizier123)。

标签: php oop object


【解决方案1】:

在谈论对象时,“匿名”不是正确的术语。最好说“匿名对象type”,但这不适用于PHP。

PHP 中的所有对象都有一个类。 “默认”类是stdClass,您可以这样创建它的对象:

$obj = new stdClass;
$obj->aProperty = 'value';

您还可以利用casting an array to an object 获得更方便的语法:

$obj = (object)array('aProperty' => 'value');
print_r($obj);

但是,请注意,将数组转换为对象可能会为那些不是有效 PHP 变量名的数组键产生“有趣”的结果——例如,here's 我的一个答案显示了当键以数字开头。

【讨论】:

  • 我也可以推送多值数组吗?
  • @CodingFreak:可以,但是:如果数组包含子数组并且您也希望将它们作为对象,则需要将每个子数组显式转换为对象。
【解决方案2】:

已经有好几年了,但我想我需要让信息保持最新!

从 PHP 7 开始,可以创建匿名类,因此您可以执行以下操作:

<?php

    class Foo {}
    $child = new class extends Foo {};

    var_dump($child instanceof Foo); // true

?>

你可以阅读更多关于这个in the manual

但我不知道它与 JavaScript 的实现有多相似,所以 JavaScript 和 PHP 中的匿名类可能存在一些差异。

【讨论】:

  • @risyasin 谢谢,更新了答案并将手动链接放入其中。
  • 将您的答案标记为正确以跟上 php7 的最新变化。谢谢@Rizier123
  • 这很有趣,但它并没有真正解决问题,因为 OP 正在询问一种方便的方法来初始化具有各种成员的对象而不创建类。我不确定是否可以使用 php 中的匿名类来做到这一点,如果可以,您没有解释如何。
【解决方案3】:

直到最近,我都是这样动态创建对象的。

$someObj = json_decode("{}");

然后:

$someObj->someProperty = someValue;

但现在我选择:

$someObj = (object)[];

然后像以前一样:

$someObj->someProperty = someValue;

当然,如果你已经知道属性和值,你可以像前面提到的那样在里面设置它们:

$someObj = (object)['prop1' => 'value1','prop2' => 'value2'];

注意:我不知道它适用于哪个版本的 PHP,因此您需要注意这一点。但我认为第一种方法(如果在构造时没有设置属性也很短)应该适用于所有具有 json_encode/json_decode 的版本

【讨论】:

  • 这和 $someObj = new \stdClass() 有什么不同?
【解决方案4】:

是的,这是可能的!使用这个简单的PHP Anonymous Object 类。它是如何工作的:

// 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 那样动态定义方法。

【讨论】:

  • 你可以使用create_function来模拟匿名函数。
  • 我认为他只是想要一种巧妙的方法来用一些值初始化 stdClass 对象。你能用你的方法做到这一点吗?
【解决方案5】:

将数组转换为对象(但这不是递归子孩子):

$obj = (object)  ['myProp' => 'myVal'];

【讨论】:

    【解决方案6】:

    如果您想模仿 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。这是从a comment on PHP: Classes and Objects 窃取的。

    【讨论】:

      【解决方案7】:

      anonymous classes 的支持从 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();
      

      【讨论】:

        【解决方案8】:

        来自 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。此外,这三个都将 json_encode() 转换为一个简单的 JS 对象 {}:

        <?php
        
        echo json_encode([
            new \stdClass,
            new class{},
            (object)[],
        ]);
        
        ?>
        

        输出:

        [{},{},{}]
        

        https://www.php.net/manual/en/language.types.object.php

        【讨论】:

          【解决方案9】:

          Anoynmus 对象wiki

          
          $object=new class (){
          
          
          };
          
          

          【讨论】:

            【解决方案10】:

            如果您想创建具有动态属性的对象(如在 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
            

            【讨论】:

              【解决方案11】:

              在 PHP 的情况下可以应用相同的技术吗?

              否 - 因为 javascript 使用对象的原型/直接声明 - 在 PHP(和许多其他 OO 语言)中,对象只能从类中创建。

              所以问题就变成了——你能不能创建一个匿名类。

              再次,答案是否定的 - 如果无法引用该类,您将如何实例化它?

              【讨论】:

              • 创建匿名类的实例不需要名称。 Java:Object var = new Object() { ... }; -- C++:class { ... } var;
              • 您现在可以在 PHP 中创建匿名类。
              【解决方案12】:

              对于想要递归对象的人:

              $o = (object) array(
                  'foo' => (object) array(
                      'sub' => '...'
                  )
              );
              
              echo $o->foo->sub;
              

              【讨论】:

                猜你喜欢
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 2014-10-31
                • 1970-01-01
                • 2023-03-16
                • 2010-10-13
                • 2010-09-11
                相关资源
                最近更新 更多