草庐IT

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

coder 2024-04-16 原文

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

<?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 - SimpleXML 和 foreach 循环中设置值的差异的更多相关文章

  1. ruby - 将差异补丁应用于字符串/文件 - 2

    对于具有离线功能的智能手机应用程序,我正在为Xml文件创建单向文本同步。我希望我的服务器将增量/差异(例如GNU差异补丁)发送到目标设备。这是计划:Time=0Server:hasversion_1ofXmlfile(~800kiB)Client:hasversion_1ofXmlfile(~800kiB)Time=1Server:hasversion_1andversion_2ofXmlfile(each~800kiB)computesdeltaoftheseversions(=patch)(~10kiB)sendspatchtoClient(~10kiBtransferred)Cl

  2. ruby - 树顶语法无限循环 - 2

    我脑子里浮现出一些关于一种新编程语言的想法,所以我想我会尝试实现它。一位friend建议我尝试使用Treetop(Rubygem)来创建一个解析器。Treetop的文档很少,我以前从未做过这种事情。我的解析器表现得好像有一个无限循环,但没有堆栈跟踪;事实证明很难追踪到。有人可以指出入门级解析/AST指南的方向吗?我真的需要一些列出规则、常见用法等的东西来使用像Treetop这样的工具。我的语法分析器在GitHub上,以防有人希望帮助我改进它。class{initialize=lambda(name){receiver.name=name}greet=lambda{IO.puts("He

  3. ruby-on-rails - 在 Ruby 中循环遍历多个数组 - 2

    我有多个ActiveRecord子类Item的实例数组,我需要根据最早的事件循环打印。在这种情况下,我需要打印付款和维护日期,如下所示:ItemAmaintenancerequiredin5daysItemBpaymentrequiredin6daysItemApaymentrequiredin7daysItemBmaintenancerequiredin8days我目前有两个查询,用于查找maintenance和payment项目(非排他性查询),并输出如下内容:paymentrequiredin...maintenancerequiredin...有什么方法可以改善上述(丑陋的)代

  4. ruby - RuntimeError(自动加载常量 Apps 多线程时检测到循环依赖 - 2

    我收到这个错误:RuntimeError(自动加载常量Apps时检测到循环依赖当我使用多线程时。下面是我的代码。为什么会这样?我尝试多线程的原因是因为我正在编写一个HTML抓取应用程序。对Nokogiri::HTML(open())的调用是一个同步阻塞调用,需要1秒才能返回,我有100,000多个页面要访问,所以我试图运行多个线程来解决这个问题。有更好的方法吗?classToolsController0)app.website=array.join(',')putsapp.websiteelseapp.website="NONE"endapp.saveapps=Apps.order("

  5. ruby-on-rails - 如何在 Rails 中设置路由的默认格式? - 2

    路由有如下代码:resources:orders,only:[:create],defaults:{format:'json'}resources:users,only:[:create,:update],defaults:{format:'json'}resources:delivery_types,only:[:index],defaults:{format:'json'}resources:time_corrections,only:[:index],defaults:{format:'json'}是否可以使用1个字符串为所有资源设置默认格式,每行不带“默认值”散列?谢谢。

  6. ruby-on-rails - environment.rb 中设置的常量在开发模式中消失 - 2

    了解Rails缓存如何工作的人可以真正帮助我。这是嵌套在Rails::Initializer.runblock中的代码:config.after_initializedoSomeClass.const_set'SOME_CONST','SOME_VAL'end现在,如果我运行script/server并发出请求,一切都很好。然而,在我的Rails应用程序的第二个请求中,一切都因单元化常量错误而变得糟糕。在生产模式下,我可以成功发出第二个请求,这意味着常量仍然存在。我已通过将以上内容更改为以下内容来解决问题:config.after_initializedorequire'some_cl

  7. ruby - Ruby 中的闭包和 for 循环 - 2

    我是Ruby的新手,有些闭包逻辑让我感到困惑。考虑这段代码:array=[]foriin(1..5)array[5,5,5,5,5]这对我来说很有意义,因为i被绑定(bind)在循环之外,所以每次循环都会捕获相同的变量。使用每个block可以解决这个问题对我来说也很有意义:array=[](1..5).each{|i|array[1,2,3,4,5]...因为现在每次通过时都单独声明i。但现在我迷路了:为什么我不能通过引入一个中间变量来修复它?array=[]foriin1..5j=iarray[5,5,5,5,5]因为j每次循环都是新的,我认为每次循环都会捕获不同的变量。例如,这绝对

  8. ruby-on-rails - Sunspot:如何对具有不同值的多个字段进行全文查询? - 2

    我想用sunspot重现以下原始solr查询q=exact_term_text:fooORterm_textv:foo*ORalternate_text:bar*但我无法通过标准的太阳黑子界面理解这是否可能以及如何实现,因为看起来:fulltext方法似乎不接受多个文本/搜索字段参数我不知道将什么参数作为第一个参数传递给fulltext,就好像我通过了"foo"或"bar"结果不匹配如果我传递一个空参数,我得到一个q=*:*范围过滤器(例如with(:term).starting_with('foo*')(顾名思义)作为过滤器查询应用,因此不参与评分。似乎可以手动编写字符串(或者可能使

  9. ruby-on-rails - 如何在回形针 ruby​​ on rails 中设置默认图像 - 2

    最近我安装了Paperclipgem,我正在努力让默认图像在我的系统上工作,我将图像文件放在assets/images/pic.png中。这是我的模型User中的代码:has_attached_file:pic,:styles=>{:medium=>"300x300>",:thumb=>"100x100>"},:default_url=>'missing_:avatar.png'#:default_url=>'assets/images/avatar.png'has_attached_file:attach这是我的AddPicPaperClip迁移中的代码:defself.upadd_

  10. ruby - :variable and @variable 之间的差异 - 2

    作为RubyonRails新手,我明白“@”和“:”引用有不同的含义。我看到了thispost在SO中,其中描述了一些差异。@表示实例变量(例如@my_selection):表示别名(例如:my_selection)我遇到了一个情况,我有一个标准的MVC页面,类似于我的网络应用程序中的所有其他表单/页面。html.erb片段route.rb片段resources:my_selections当我尝试访问此页面时,出现此错误:NoMethodErrorinselections#createShowingC:/somedir/myapp/app/views/my_selections/ind

随机推荐