我正试图找到一种方法来改变引用变量两个级别,同时避免Deprecated: Call-time pass-by-reference has been deprecated
我查看了this和this,似乎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
两个级别)
好的,这是我解释问题的最好机会,请告诉我你是否需要澄清。
答案 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
的情况下插入文档时驱动程序为您所做的事情。