2024年PHP开发者大会日本站

ArrayObject 类

(PHP 5, PHP 7, PHP 8)

简介

此类允许对象像数组一样工作。

注意: 使用此类包装对象从根本上是有缺陷的,因此不建议将其用于对象。

类概要

class ArrayObject implements IteratorAggregate, ArrayAccess, Serializable, Countable {
/* 常量 */
public const int STD_PROP_LIST;
public const int ARRAY_AS_PROPS;
/* 方法 */
public __construct(array|object $array = [], int $flags = 0, string $iteratorClass = ArrayIterator::class)
public append(mixed $value): void
public asort(int $flags = SORT_REGULAR): true
public count(): int
public getFlags(): int
public ksort(int $flags = SORT_REGULAR): true
public natcasesort(): true
public natsort(): true
public offsetExists(mixed $key): bool
public offsetGet(mixed $key): mixed
public offsetSet(mixed $key, mixed $value): void
public offsetUnset(mixed $key): void
public serialize(): string
public setFlags(int $flags): void
public setIteratorClass(string $iteratorClass): void
public uasort(callable $callback): true
public uksort(callable $callback): true
public unserialize(string $data): void
}

预定义常量

ArrayObject 标志

ArrayObject::STD_PROP_LIST

对象的属性在作为列表访问时具有其正常功能(var_dump()foreach等)。

ArrayObject::ARRAY_AS_PROPS

条目可以作为属性访问(读写)。ArrayObject 类使用其自身的逻辑来访问属性,因此在尝试读取或写入动态属性时不会引发警告或错误。

目录

添加注释

用户贡献的注释 10 条注释

php5 dot man at lightning dot hu
12 年前
如您所知,ArrayObject 不是数组,因此您不能使用内置的数组函数。这是一个解决方法

使用您自己的类扩展 ArrayObject 类并实现此魔术方法

<?php
public function __call($func, $argv)
{
if (!
is_callable($func) || substr($func, 0, 6) !== 'array_')
{
throw new
BadMethodCallException(__CLASS__.'->'.$func);
}
return
call_user_func_array($func, array_merge(array($this->getArrayCopy()), $argv));
}
?>

现在您可以对任何 array_* 函数执行此操作
<?php
$yourObject
->array_keys();
?>
- 不要忘记省略第一个参数 - 它会自动处理!

注意:如果您处理大型数据集,您可能需要编写自己的函数。
rwn dot gallego at gmail dot com
11 年前
这里有关于 ArrayObject 标志(STD_PROP_LIST 和 ARRAY_AS_PROPS)的更好解释

http://stackoverflow.com/a/16619183/1019305

感谢 JayTaph
bub at gmail dot com
2 年前
如果您需要集合的最后一个键,请使用
<?php
array_key_last
($this->getArrayCopy())
?>

在扩展类中,它可能看起来像这样
<?php
class Collection extends ArrayObject
{
public function
lastKey(): int
{
return
array_key_last($this->getArrayCopy());
}
}
?>

如果您想使用任何类型安全的集合
<?php
class BookCollection extends Collection
{
public function
add(Book $book) : void
{
$this->offsetSet($book->id, $book);
}

// 注意返回类型“Book”
public function get(int $bookId) : Book
{
$this->offsetGet($bookId);
}
}
?>
MarkAndrewSlade at gmail dot com
13 年前
我发现 STD_PROP_LIST 的描述有点含糊,所以我整理了一个简单的演示来展示它的行为

<?php

$a
= new ArrayObject(array(), ArrayObject::STD_PROP_LIST);
$a['arr'] = 'array data';
$a->prop = 'prop data';
$b = new ArrayObject();
$b['arr'] = 'array data';
$b->prop = 'prop data';

// ArrayObject 对象
// (
// [prop] => prop data
// )
print_r($a);

// ArrayObject 对象
// (
// [arr] => array data
// )
print_r($b);

?>
deminy at deminy dot net
15 年前
通常情况下,变量 $this 不能在对象上下文中用作数组。例如,以下代码段将导致致命错误

<?php
class TestThis {
public function
__set($name, $val) {
$this[$name] = $val;
}

public function
__get($name) {
return
$this[$name];
}
}

$obj = new TestThis();
$obj->a = 'aaa';
echo
$obj->a . "\n";
?>

但是,当 $this 在 ArrayObject 对象中使用时,情况有所不同。例如,以下代码段是有效的

<?php
class TestArrayObject extends ArrayObject {
public function
__set($name, $val) {
$this[$name] = $val;
}

public function
__get($name) {
return
$this[$name];
}
}

$obj = new TestArrayObject();
$obj->a = 'aaa';
echo
$obj->a . "\n";
?>
Gilles A
10 年前
// STD_PROP_LIST 和 ARRAY_AS_PROP 组合示例
<?php
$ao
= new ArrayObject();
$ao ->setFlags(ArrayObject::STD_PROP_LIST|ArrayObject::ARRAY_AS_PROPS);

$ao->prop = 'prop data';
$ao['arr'] = 'array data';

print_r($ao);

?>

// 结果

ArrayObject 对象
(
[storage:ArrayObject:private] =&gt; 数组
(
[prop] => prop data
[arr] => array data
)

)
hello at rayfung dot hk
3 年前
如果您想将内置数组函数与 ArrayObject 一起使用,请存储迭代器实例并在 offsetGet 中以引用的方式返回值。

<?php
class Collection extends \ArrayObject {
public function
__construct(array $data = [])
{
if (!
\is_array($data) && !\array_key_exists('ArrayAccess', class_implements($data))) {
$data = [$data];
}

$this->iterator = $this->getIterator();
parent::__construct($data);
}

public function &
offsetGet($index)
{
$value = &$this->iterator[$index] ?? null;

return
$value;
}
}
?>
Nguyen Vuong
6年前
您可以很容易地意识到,ArrayObject 可以像在 ArrayIterator 中一样使用各种函数来迭代对象作为数组。但是,您需要首先使用 getIterator() 来“激活”这些函数(rewind、valid、next 等…)。实际上,此函数继承自 Iterator Aggregate 接口。

请看下面的基本示例。结果相同

<?php

$array
= [1, 2, 3, 4];
$a = new ArrayObject($array);
$b = new ArrayIterator($array);

$iterator = $a->getIterator();

for(
$iterator->rewind(); $iterator->valid(); $iterator->next()){
echo
$iterator->current()*2;

}

for(
$b->rewind(); $b->valid(); $b->next()){
echo
$b->current()*2;

}

//结果相同 2468 和 2468
sfinktah at php dot spamtrak dot org
13 年前
如果您计划从 ArrayObject 派生您自己的类,并希望保持完整的 ArrayObject 功能(例如能够转换为数组),则必须使用 ArrayObject 自己的私有属性“storage”。

由于无法直接执行此操作,因此必须使用 ArrayObject 的 offset{Set,Get,Exists,Unset} 方法间接操作它。

作为额外好处,这意味着您继承了所有迭代和其他功能,并且可以完全正常工作。

对于从未实现过自己的 ArrayObject 类的人来说,这听起来可能很明显……但事实并非如此。

<?php

class MyArrayObject extends ArrayObject {
static
$debugLevel = 2;

static public function
sdprintf() {
if (static::
$debugLevel > 1) {
call_user_func_array("printf", func_get_args());
}
}

public function
offsetGet($name) {
self::sdprintf("%s(%s)\n", __FUNCTION__, implode(",", func_get_args()));
return
call_user_func_array(array(parent, __FUNCTION__), func_get_args());
}
public function
offsetSet($name, $value) {
self::sdprintf("%s(%s)\n", __FUNCTION__, implode(",", func_get_args()));
return
call_user_func_array(array(parent, __FUNCTION__), func_get_args());
}
public function
offsetExists($name) {
self::sdprintf("%s(%s)\n", __FUNCTION__, implode(",", func_get_args()));
return
call_user_func_array(array(parent, __FUNCTION__), func_get_args());
}
public function
offsetUnset($name) {
self::sdprintf("%s(%s)\n", __FUNCTION__, implode(",", func_get_args()));
return
call_user_func_array(array(parent, __FUNCTION__), func_get_args());
}
}

$mao = new MyArrayObject();
$mao["name"] = "bob";
$mao["friend"] = "jane";
print_r((array)$mao);

/* 输出:

offsetSet(name,bob)
offsetSet(friend,jane)
Array
(
[name] => bob
[friend] => jane
) */
?>

如果您希望使用“数组作为属性”标志,您只需在构造函数中包含它即可

<?php parent::setFlags(parent::ARRAY_AS_PROPS); ?>

这将允许您执行以下示例中的操作,而无需重写 __get 或 __set。

<?php
$mao
->name = "Phil";
echo
$mao["name"]; /* 输出 "Phil" */
?>
rudie
6年前
如果您希望数值 ArrayObject 对象与 json_encode() 很好地配合使用,请实现 JsonSerializable

class JsonSerializableArrayObject extends ArrayObject implements JsonSerializable {
function jsonSerialize() {
return $this->getArrayCopy();
}
}

对于关联 ArrayObject 对象,这没有必要,但对于数值数组来说是必要的,否则它们将被格式化为

{"0":"jaap","1":"karel"}

而不是

["jaap","karel"]
To Top