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
12 年前
我发现 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 Object
// (
// [prop] => prop data
// )
print_r($a);

// ArrayObject Object
// (
// [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";
?>

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

<?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
9 年前
// 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; Array
(
[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;
}
}
?>
Vuong Nguyen
6 年前
您可以轻松地意识到 ArrayObject 可以使用各种函数(例如 rewind、valid、next 等)来迭代对象作为数组。但是,您需要先使用 getIterator() 来“激活”这些函数。实际上,此函数继承自 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