【发布时间】:2017-04-03 06:31:40
【问题描述】:
我对 PHP 7 中的新功能非常满意。但我对如何在 PHP 7 中返回对象数组感到困惑。
例如,我们有一个类Item,我们想从我们的函数中返回一个该类的对象数组:
function getItems() : Item[] {
}
但是这样不行。
【问题讨论】:
我对 PHP 7 中的新功能非常满意。但我对如何在 PHP 7 中返回对象数组感到困惑。
例如,我们有一个类Item,我们想从我们的函数中返回一个该类的对象数组:
function getItems() : Item[] {
}
但是这样不行。
【问题讨论】:
我实际上明白你的意思,但不幸的是,答案是你不能那样做。 PHP7 缺乏这种表达能力,因此您可以声明您的函数以返回“数组”(一个通用数组),或者您必须创建一个新的 ItemArray 类,它是一个 Item 数组(但这意味着您必须自己编写代码)。
目前没有办法表达“我想要一个 Item 数组”实例。
编辑:作为补充参考,这里是您想做的"array of" RFC,由于各种原因,它已被拒绝。
【讨论】:
您可以使用docblocks 以这种方式输入提示。
像 PhpStorm 这样的 PHP 编辑器 (IDE) 非常支持这一点,并且在迭代此类数组时会正确解析该类。
/**
* @return YourClass[]
*/
public function getObjects(): iterable
PHPStorm 也支持嵌套数组:
/**
* @return YourClass[][]
*/
public function getObjects(): iterable
较新版本的 PHPStorm 支持 phpstan/psalm 格式:
/**
* @return array<int, YourObject>
*/
public function getObjects(): array
【讨论】:
当前版本的 PHP 不支持对象数组的内置类型提示,因为没有“对象数组”这样的数据类型。在某些上下文中,类名和 array 可以解释为类型,但不能同时解释为两者。
其实你可以通过创建一个基于ArrayAccess接口的类来实现这种严格的类型提示,例如:
class Item
{
protected $value;
public function __construct($value)
{
$this->value = $value;
}
}
class ItemsArray implements ArrayAccess
{
private $container = [];
public function offsetSet($offset, $value)
{
if (!$value instanceof Item) {
throw new Exception('value must be an instance of Item');
}
if (is_null($offset)) {
$this->container[] = $value;
} else {
$this->container[$offset] = $value;
}
}
public function offsetExists($offset)
{
return isset($this->container[$offset]);
}
public function offsetUnset($offset)
{
unset($this->container[$offset]);
}
public function offsetGet($offset)
{
return isset($this->container[$offset]) ? $this->container[$offset] : null;
}
}
function getItems() : ItemsArray
{
$items = new ItemsArray();
$items[0] = new Item(0);
$items[1] = new Item(2);
return $items;
}
var_dump((array)getItems());
输出
array(2) {
["ItemsArrayitems"]=>
array(0) {
}
["container"]=>
array(2) {
[0]=>
object(Item)#2 (1) {
["value":protected]=>
int(0)
}
[1]=>
object(Item)#3 (1) {
["value":protected]=>
int(2)
}
}
}
【讨论】:
目前不可能。但是您可以使用自定义数组类来实现您的预期行为
function getItems() : ItemArray {
$items = new ItemArray();
$items[] = new Item();
return $items;
}
class ItemArray extends \ArrayObject {
public function offsetSet($key, $val) {
if ($val instanceof Item) {
return parent::offsetSet($key, $val);
}
throw new \InvalidArgumentException('Value must be an Item');
}
}
【讨论】:
我相信这就是你要找的东西
<?php
class C {}
function objects()
{
return array (new C, new C, new C);
}
list ($obj1, $obj2, $obj3) = objects();
var_dump($obj1);
var_dump($obj2);
var_dump($obj3);
?>
【讨论】: