【问题标题】:Call time pass by reference, two levels of referencing?调用时间按引用传递,二级引用?
【发布时间】:2012-10-12 11:13:55
【问题描述】:

总结

我正在尝试找到一种方法将引用变量向上更改两级,同时避免Deprecated: Call-time pass-by-reference has been deprecated

我所做的研究

我查看了thisthis,似乎call_user_func_array 可以使警告静音,但我认为我遗漏了一些东西。

问题

我正在使用 MongoDB 和 PHP,以下方法属于一个模型,并在保存之前简单地检查通过引用传递给它的输入的架构。

// $this->collection is the MongoCollection object
public function save(&$entry) {

    if( empty($entry) ) return false;
    if( !$this->checkSchema($entry) ) $this->throwDbError('Schema violation in `' . get_class($this) . '`');

    try { return $this->collection->save(&$entry); } // <---- want to avoid using &
    catch (Exception $e) { return $this->throwDbError($e); }

}

MongoCollection::save ($this-&gt;collection-&gt;save) 将使用新的文档 ID 将 _id 字段附加到 $entry 上。但是,此更改并未反映在传递给上述方法的$entry除非我通过引用传递它的调用时间。 (本质上我希望MongoCollection::save 能够修改$entry 两级

好的,这是我解释问题的最佳方法,如果您需要澄清,请告诉我。

【问题讨论】:

  • "// & 符号之前,然后按“删除”。说真的,在 php5 中它没有任何意义。您只能在函数声明中指定该变量作为引用传递。
  • 我知道我可以,但是传递给上述方法的 $entry 没有附加 [_id] (我需要)
  • @NathanKot 似乎,$entry 应该是一个对象。要么,要么记住,方法可以有一个返回值;)
  • @Nathan Kot:好吧,那只是一个 mongodb 驱动程序错误
  • @KingCrunch:是的,我也是这么想的,但是没有 - php.net/manual/en/mongocollection.save.php

标签: php mongodb pass-by-reference


【解决方案1】:

MongoCollection::save()MongoCollection::insert() 都可以通过设置_id 键来修改它们的参数,尽管save() (I'll fix that soon) 似乎没有记录。在内部,这两种方法都在修改传递给 C 函数的原始 zval。如果我不得不猜测,这是因为将第一个参数指定为引用会导致无法传递数组文字。因此,无论如何,扩展程序都会欺骗并修改参数,其副作用是无法修改通过引用传递的内容。

我测试了下面的代码,它似乎以在你的保存方法中复制数组参数为代价来解决这个问题:

public function save(&$entry)
{
    if (empty($entry)) {
        return false;
    }

    if (!$this->checkSchema($entry)) {
        $this->throwDbError('Schema violation in `' . get_class($this) . '`');
    }

    try {
        $entryCopy = $entry;
        $saveResult = $this->collection->save($entryCopy);

        if (!isset($entry['_id']) && isset($entryCopy['_id']) {
            $entry['_id'] = $entryCopy['_id'];
        }

        return $saveResult; 
    } catch (Exception $e) {
        return $this->throwDbError($e);
    }
}

如果你愿意,我想你总是可以将_id 属性复制回$entry。或者,您可以使用数组复制并简单地将 $entry[_id] 初始化为新的 MongoId 实例(如果尚未设置)。这基本上就是驱动程序在插入没有_id 的文档时为您执行的操作。

【讨论】:

  • "这是因为将第一个参数指定为引用会导致无法传递数组文字" 这似乎是放弃正确性的糟糕理由
  • @jmikola 感谢您的回答,这是我最终采用的方法(虽然不优雅) - 但我想我会将其更改为您手动初始化 MongoID 的第二个建议
猜你喜欢
  • 2011-05-08
  • 1970-01-01
  • 2013-04-12
  • 1970-01-01
  • 2011-07-07
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-01-16
相关资源
最近更新 更多