通过参考传递呼叫时间,两个级别的参考?

时间:2012-10-12 11:13:55

标签: php mongodb pass-by-reference

摘要

我正试图找到一种方法来改变引用变量两个级别,同时避免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->collection->save)会将_id字段附加到$entry以及新文档ID。但是,此更改未反映在传递到上方的$entry中,除非我通过引用传递了它的调用时间。 (基本上我希望MongoCollection::save能够修改$entry 两个级别

好的,这是我解释问题的最好机会,请告诉我你是否需要澄清。

1 个答案:

答案 0 :(得分:0)

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

我测试了以下代码,这似乎解决了这个问题,但代价是在save方法中复制数组参数:

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的情况下插入文档时驱动程序为您所做的事情。