在php中创建匿名对象


141

众所周知,使用JavaScript创建匿名对象很容易,就像下面的代码一样:

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

alert(object.p1[1]);

输出:

an alert is raised with value "johnny"

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


1
注意:这是一个古老的问题,因此接受的答案已过期。现在已将要求的功能添加到PHP 7中。请参阅@ Rizier123的以下答案。
辛巴

@Simba-感谢您指出。您想在此页面上的StackOverflow上发布答案以帮助将来的访问者吗?
Sujit Agarwal

1
我不需要 此信息已经存在答案(请参阅下文,@ Rizier123)。
辛巴

Answers:


40

已经有好几年了,但是我认为我需要保持最新信息!

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

<?php

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

    var_dump($child instanceof Foo); // true

?>

您可以在手册中详细了解

但是我不知道它的实现与JavaScript有多么相似,因此JavaScript和PHP中的匿名类之间可能会有一些差异。


@risyasin谢谢,更新了答案,并在其中添加了手动链接。
Rizier123

将您的答案标记为正确,以跟上php7的最新更改。感谢@ Rizier123
Sujit Agarwal

3
这很有趣,但是并没有真正解决这个问题,因为OP正在询问一种方便的方法来用各种成员初始化对象而不创建类。我不确定php中的匿名类是否可以用来做到这一点,如果可以,您没有解释如何做。
amh15

228

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

PHP中的所有对象都有一个类。“默认”类为stdClass,您可以通过以下方式创建它的对象:

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

您还可以利用将数组强制转换为对象以获得更方便的语法:

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

但是,建议将数组强制转换为对象可能会为那些无效PHP变量名称的数组键产生“有趣的”结果-例如,这是我的回答,它显示键以数字开头时发生的情况。


1
我也可以推送多值数组吗?
Sujit Agarwal

2
@CodingFreak:可以,但是:如果数组包含子数组,并且您也希望将它们作为对象,则需要将每个数组都明确地转换为对象。
乔恩

21

是的,有可能!使用这个简单的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模拟匿名函数。
Mihailoff 2013年

我认为他只是想要一种巧妙的方法来初始化带有某些值的stdClass对象。你能用你的方法做到吗?
amh15

18

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

$someObj = json_decode("{}");

然后:

$someObj->someProperty = someValue;

但是现在我去:

$someObj = (object)[];

然后像以前一样:

$someObj->someProperty = someValue;

当然,如果您已经知道属性和值,则可以如前所述在内部设置它们:

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

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


1
与去$ someObj = new \ stdClass()有什么不同?
JamesNZ

9

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

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

7

如果您想模仿JavaScript,则可以创建一个class 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:类和对象的评论中窃取的。


3

自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();

1

在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/zh/language.types.object.php


0

如果您要创建具有动态属性的对象(如javascript中的对象),而又没有收到未定义属性的警告,那么当您尚未为property设置值时

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

0

可以在PHP中应用相同的技术吗?

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

因此问题就变成了-您可以创建一个匿名类吗?

同样,答案是否定的-您将如何在无法引用该类的情况下实例化该类?


您不需要名称即可创建匿名类的实例。Java:Object var = new Object() { ... };-C ++:class { ... } var;
TheOperator'1

1
您现在可以在PHP中创建匿名类。
维克多

0

对于想要递归对象的人:

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

echo $o->foo->sub;

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.