1

在 PHP 中,您可以在元素上使用方括号来访问属性:

$node = /* SimpleXMLElement */
$id = $node['id'];

奇怪的是,这$id不是一个字符串,而是另一个SimpleXMLElement. 为什么不是字符串?我发现自己strval()到处都在使用它。

方括号是如何工作的?我可以用自己的课程做到这一点吗?我在文档中没有看到任何关于此的内容。

4

4 回答 4

3

您可以通过实现ArrayAccess 接口(它是 PHP 标准库的一部分)来提供对对象的类似 Array 的访问。这个接口是“即使你没有安装完整的 PHP 标准库扩展,你仍然可以在 PHP 5 中使用这个接口”的东西之一。

通过实现这个接口,并为你的类定义四个方法

public boolean offsetExists  ( string $offset  )
public mixed offsetGet ( string $offset )
public void offsetSet ( string $offset , string $value )
public void offsetUnset ( string $offset )

您应该能够在实例化对象中使用方括号。

至于 SimpleXML 本身,我不确定它是否真的实现了 ArrayAccess 接口,或者是否在 PHP 源代码的幕后发生了其他事情,赋予了它这些超能力。

于 2009-03-19T21:59:35.180 回答
1

我相信您可以扩展 SimpleXML 类,并在其中实现 ArrayAccess。

于 2009-03-21T02:06:54.393 回答
1

至于 SimpleXML 本身,它是一个内部类。它为 PHP 用户空间实现的唯一接口是Traversable.

在内部使用方括号访问时,SimpleXML 根据索引/键的值和类型查找内容。

如果类型是整数(长整数),则尝试查找零索引、编号的元素并提供其值。如果您有一个具体的节点元素,例如$root根元素,$root[0]将表示该元素的值:

$root = new SimpleXMLElement('<root a="vala"></root>');
$root[0] = 'hello'; 
# <root a="vala">hello</root>
#                ^^^^^- changed value                     

根元素有点无趣,因为只存在一个。有父元素的元素更有趣。

$root = new SimpleXMLElement('<root a="vala"><child /></root>');
$root->child[0] = 'hello'; 
# <root a="vala"><child>hello</child></root>
#                       ^^^^^- changed value

设置第一个child元素的节点值。一个 index up-one 将添加一个新的孩子:

$root = new SimpleXMLElement('<root a="vala"><child /></root>');
$root->child[1] = 'hello'; 
# <root a="vala"><child/><child>hello</child></root>
#                        ^--  added child --^

这几乎与数组一样工作。整数字符串,就像整数一样工作:

$root->child['1'] = 'hello'; 
# <root a="vala"><child/><child>hello</child></root>
#                        ^--  added child --^

并将括号留空,将在末尾添加一个新元素:

$root->child[] = 'hello';
$root->child[] = 'world';
# <root a="vala"><child/><child>hello</child><child>world</child></root>

到目前为止,对于整数和“无”偏移。与标准 PHP 数组一样,这不能与传递NULL. 它将被转换为空字符串""

对于任何字符串,SimpleXML 将查找属性节点而不是子元素节点:

$root = new SimpleXMLElement('<root a="vala"></root>');
echo $root['a'], "\n"; # vala

这也适用于添加属性:

$root = new SimpleXMLElement('<root a="vala"></root>');
$root['b'] = 'hello'; # <root a="vala" b="hello"/>

一个极端情况是使用一个空字符串 ( "") 或者NULL因为 simplexml 然后错误地指出没有名称的属性是无效的。有意义,因为属性必须有一个名称:

警告:main():无法在...中写入或创建未命名属性

另一个更特殊的情况是__toString魔术方法的支持。如果您将对象作为偏移量传递,SimpleXML 将尝试通过魔术方法将其转换为字符串。然后它将使用返回的字符串,如上所述。


总结:该类SimpleXMLElement没有实现ArrayAccess接口,但由于它是一个内部类,它可以添加类似数组的行为。而 SimpleXML 正是这样做的。

PHP 源代码中的实用程序函数称为sxe_prop_dim_read.


但是当你想对你的类做类似的事情时呢?

这就是ArrayAccess接口的用途。在您自己的类中实现它。PHP 已经在内部为您完成了一些工作,以使偏移量更像数组:整数保持整数;像整数这样的字符串被转换为整数,布尔值被转换为整数。

然而ArrayAccess,允许的不仅仅是标准数组:有效的偏移量是浮点数、NULL、数组和对象。

特别是使用NULL,您无法区分设置偏移量NULL或设置新元素 - 两种情况都将提供NULL偏移量。

另一个问题提供了接口的示例实现:PHP、SPL、ArrayAccess 接口

于 2012-11-05T13:43:50.453 回答
0

我想这是魔术方法__get()

编辑:我想我猜错了。还不知道数组访问接口。

于 2009-03-19T21:59:36.443 回答