在 php 中创建匿名对象

正如我们所知,用 JavaScript 创建匿名对象很容易,如下面的代码所示:

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


alert(object.p1[1]);

产出:

an alert is raised with value "johnny"

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

97472 次浏览

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

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

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

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

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

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

如果希望模拟 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这是从 关于 PHP 的注释: 类和对象偷来的。

同样的技术可以应用于 PHP 吗?

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

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

同样,答案是否定的——如何在不能引用它的情况下实例化这个类?

是的,这是可能的! 使用这个简单的 PHP 匿名对象类。它是如何工作的:

// 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 所做的那样。

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

从 PHP7开始,就可以创建匿名类,所以您可以这样做:

<?php


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


var_dump($child instanceof Foo); // true


?>

你可以阅读更多关于这个 在手册里的内容

但是我不知道它的实现与 JavaScript 有多相似,所以在 JavaScript 和 PHP 中的匿名类之间可能有一些区别。

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

直到最近,我都是这样在运行中创建对象的。

$someObj = json_decode("{}");

然后:

$someObj->someProperty = someValue;

但现在我要说:

$someObj = (object)[];

然后像以前一样:

$someObj->someProperty = someValue;

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

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

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

将数组转换为 object (但这不是递归到子子子元素):

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

对于需要递归对象的用户:

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


echo $o->foo->sub;

从 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) {}


?>

$objec1和 $objec3是相同的类型,但是 $objec1!= = $objec3.另外,这三个对象都将 json _ encode ()转换为一个简单的 JS 对象{} :

<?php


echo json_encode([
new \stdClass,
new class{},
(object)[],
]);


?>

产出:

[{},{},{}]

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

匿名类的支持从 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();

异常物体 维基百科


$object=new class (){




};