【问题标题】:Unset object variable's property in a method, affected its value in parent scope?在方法中取消设置对象变量的属性,影响其在父范围内的值?
【发布时间】:2016-03-22 13:42:14
【问题描述】:

我制作了一个小型库来读取数据库导出的 xml 文件,并将其输出为结构化关联数组。它还可以按表格列过滤输出。

完成代码后,当我玩这个类时,我发现了一些奇怪的东西。 unset 的行为就像变量是通过引用传递的一样。

我找不到任何可能的错误,所以我提出了设置$this->rows 的特定方法,希望有人能启发我。

private function populateData($rowLimit)
    {
        if (!$this->getColumns()) {
            throw new ReaderException(__FUNCTION__ . " # Unable to get columns name.");
        }

        // database->tableName->rows
        $rows = $this->getSimpleXmlElement()->children()->children();

        if ($this->getFilteredColumns()) {
            $toRemoves = array_values(array_diff($this->getColumns(),
                $this->getFilteredColumns()));
            foreach ($rows as $row) {
                foreach ($toRemoves as $toRemove) {
                    unset($row->{$toRemove});
                }
            }
        }

        $rows = $this->simpleXmlToArray($rows)['row'];

        if ($rowLimit) {
            $limited = [];
            for ($i = 0; $i < $rowLimit; $i++) {
                $limited[] = $rows[$i];
            }
            $this->setRows($limited);
        } else {
            $this->setRows($rows);
        }

        $structArray = [
            'database' => $this->getDatabaseName(),
            'table' => $this->getTableName(),
            'columns' => !$this->getFilteredColumns() ? $this->getColumns()
                : $this->getFilteredColumns(),
            'rows' => $this->getRows()
        ];

        $this->setStruct($structArray);

        return $this;
    }


$xml = new SomeXmlReader($companyTableFilePath);
$xml->get(1);

输出:

[
 "database" => "myDatabase",
 "table" => "companies",
 "columns" => [
   "id",
   "name",
   "license_no",
   "phone",
   "created",
   "modified",
 ],
 "rows" => [
   [
     "id" => "1",
     "name" => "SOME COMPANY NAME",
     "license_no" => "884652",
     "phone" => null,
     "created" => "2015-09-25 16:01:57",
     "modified" => "2015-09-25 16:01:57",
   ],
 ],
]

当我尝试过滤掉某些列时,我会这样做

$xml->setFilteredColumns(['id','name'])->get(1);

它按预期返回结果:列已被修剪。 输出:

[
 "database" => "myDatabase",
 "table" => "companies",
 "columns" => [
   "id",
   "name",
 ],
 "rows" => [
   [
     "id" => "1",
     "name" => "SOME COMPANY NAME",
   ],
 ],
]

然而,就在这一行之后,当我用

再次测试它时
$xml->setFilteredColumns(['id','name','phone'])->get(1);

在下一行,出了点问题。输出是:

[
 "database" => "myDatabase",
 "table" => "companies",
 "columns" => [
   "id",
   "name",
   "phone",
 ],
 "rows" => [
   [
     "id" => "1",
     "name" => "SOME COMPANY NAME",
   ],
 ],
]

经过一番追踪,我发现$this-&gt;getSimpleXmlElement()unset修改了。在此应用生命周期内,我无法再获得 $this-&gt;getSimpleXmlElement() 的完整/原始值。

我是否犯了一个根本性的错误,或者这是 PHP 语言的行为?

【问题讨论】:

    标签: php simplexml unset


    【解决方案1】:

    这里有相当多的代码需要遵循 - 考虑制作a more compact example - 但听起来你的误解很简单。

    当从一个作用域到另一个作用域时,对象永远不会被复制,因为变量不“包含”一个对象,它“指向”一个对象(这与传递引用不太一样,但效果在很多情况下是相似的)。

    因此,当您运行 unset($row-&gt;{$toRemove}); 时,您确实在编辑 $row 对象,进而扩展整个 SimpleXML 文档。

    如果您想要使用对象的副本,则必须明确“克隆”它,如 discussed in the PHP manual

    【讨论】:

      猜你喜欢
      • 2019-03-12
      • 1970-01-01
      • 2019-02-17
      • 2013-10-24
      • 2017-12-02
      • 1970-01-01
      • 2011-07-27
      • 2015-02-12
      • 1970-01-01
      相关资源
      最近更新 更多