正如我们所知,用 JavaScript 创建匿名对象很容易,如下面的代码所示:
var object = { p : "value", p1 : [ "john", "johnny" ] }; alert(object.p1[1]);
产出:
an alert is raised with value "johnny"
同样的技术可以应用在 PHP 中吗? 我们可以在 PHP 中创建匿名对象吗?
在谈论对象时,“匿名”不是正确的术语。最好是说“匿名 类型的对象”,但这并不适用于 PHP。
PHP 中的所有对象都有一个类。“ default”类是 stdClass,您可以这样创建它的对象:
stdClass
$obj = new stdClass; $obj->aProperty = 'value';
您还可以利用 将数组强制转换为对象获得更方便的语法:
$obj = (object)array('aProperty' => 'value'); print_r($obj);
但是,请注意,对于那些不是有效 PHP 变量名的数组键,将数组强制转换为对象可能会产生“有趣”的结果——例如,我的一个答案 这是显示了键以数字开头时会发生什么。
如果希望模拟 JavaScript,可以创建一个类 Object,从而获得相同的行为。当然,这不再是完全匿名的,但它将工作。
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 所做的那样。
AnObj
已经有好几年了,但是我认为我需要保持信息的更新!
从 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 = (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短。)
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 (){ };