2

概括

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

我做过的研究

我已经浏览了这个这个,似乎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->collection->save)将使用新的文档 ID附加该_id字段。但是,除非我通过引用传递调用时间,否则$entry此更改不会反映在$entry传递给上述方法的内容上。(本质上我希望能够向上修改两个级别MongoCollection::save$entry

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

4

1 回答 1

0

MongoCollection::save()MongoCollection::insert()都可以通过设置一个键来修改它们的参数_id,尽管它似乎没有记录在案save()我会尽快修复)。在内部,这两种方法都在修改传递给 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.

于 2012-10-12T17:55:37.653 回答