php - SimpleXML 和 foreach 循环中设置值的差异

标签 php simplexml

在回答上一个问题时,我发现了以下我无法理解的行为。以下代码显示了问题...

<?php
error_reporting(E_ALL);
ini_set('display_errors', 1);

$data = <<< XML
<?xml version="1.0" standalone="yes"?>
<Base>
    <Data>
        <Value></Value>
    </Data>
</Base>
XML;

$xml = simplexml_load_string($data);
foreach ( $xml->Data->Value as $value ) {
    $value = 1;
}
echo $xml->asXML().PHP_EOL;
foreach ( $xml->Data as $value ) {
    $value->Value = 1;
}
echo $xml->asXML().PHP_EOL;

我希望每个点的输出都相同,但输出是...

<?xml version="1.0" standalone="yes"?>
<Base>
    <Data>
        <Value/>
    </Data>
</Base>

<?xml version="1.0" standalone="yes"?>
<Base>
    <Data>
        <Value>1</Value>
    </Data>
</Base>

所以这似乎表明第一个循环直接访问 <Value>元素,不设置值,但间接访问它的第二个循环工作正常。

有什么区别?

最佳答案

区别与循环或引用无关,而与到底是什么 = 无关在每种情况下均表示。

第一个版本可以简化为:

$value = $xml->Data->Value;
$value = 1;

这是对变量的直接赋值,首先是一个值,然后是另一个值。旧值和新值之间没有交互,所以 $xml没有改变。


第二种情况可以这样写:

$data = $xml->Data;
$data->Value = 1;
// Or just $xml->Data->Value = 1;

在这里,我们不是给普通变量赋值,而是给对象属性赋值,诀窍是对象可以拦截该赋值,并用它做一些特殊的事情。在这种情况下,它会触发 SimpleXML 将值发送到 libxml XML 文档在内存中的表示。就好像你运行了一个像$data->setValueOfChild('Value', 1);这样的方法调用。 .


请注意,如果我们改为这样写:

$value =& $xml->Data->Value;
$value = 1;

现在第一个赋值集$value作为引用,第二个分配1到那个引用。这足以将值写入实际的对象属性,但不会触发 SimpleXML 需要的拦截。


但是,在这种特殊情况下我们可以使用一个额外的技巧:除了拦截属性访问外,SimpleXMLElement类拦截数组访问,以便您可以编写 $foo->NameThatOccursMoreThanOnce[3]$some_element['Attribute'] .所以事实证明我们可以这样写:

$value = $xml->Data->Value;
$value[0] = 1;

在这里,$valueSimpleXMLElement对象,可以拦截 $value[0] = 1就像 $value->setValueOfItem(0, 1) .

在这种情况下,该对象包含名为 <Value> 的所有元素的集合。从 <Data> 里面元素;但方便的是,即使对象已经缩小到一项,[0]只是引用相同的元素,所以这也有效:

$value = $xml->Data->Value[0];
$value[0] = 1;

最后,请注意您自己的对象也可以实现这种神奇的行为!可以使用 the __get , __set , and __unset magic methods 实现属性访问, 数组访问可以使用 the ArrayAccess interface 实现.

关于php - SimpleXML 和 foreach 循环中设置值的差异,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48081373/

相关文章:

php - 无法访问不同服务器上的Session变量

php - 使用 PHP 提取字符串的一些 XML 标记

php - 使用 simplexml 解析时如何忽略大小写?

php simplexml获取具有特定标签的所有元素

php:使用 simplexml 和 xpath 解析 rss feed

php - simplexml,返回具有相同标签的多个项目

php - 如何从post方法获取数据

php - Zimbra SOAP 创建帐户

php - 如何将多次出现的子模式捕获到一次捕获中?

php - 计算商品和数量价格然后发送电子邮件