2

概要

回避しながら、参照される変数を2レベル上に変更する方法を見つけようとしていますDeprecated: Call-time pass-by-reference has been deprecated

私が行った研究

これこれに目を通しましたが、警告を黙らせることができるようcall_user_func_arrayですが、何かが足りないと思います。

問題

私は PHP で MongoDB を使用しています。次のメソッドはモデルに属し、参照によって渡された入力のスキーマを保存する前にチェックするだけです。

// $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、上記のメソッドに渡されるに反映されていません。(本質的には、 2 レベル上に変更できるようにしたい)MongoCollection::save$entry

わかりました。これが問題を説明する最善の方法です。説明が必要な場合はお知らせください。

4

1 に答える 1

0

MongoCollection::save()MongoCollection::insert()はどちらも、キーを設定することで引数を変更できますが、_idドキュメントには記載されていないようですsave()(すぐに修正します)。内部的には、両方のメソッドが 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

于 2012-10-12T17:55:37.653 に答える