PHP 5.4呼び出し時の参照渡し-簡単な修正が利用可能ですか?


219

この問題を簡単に修正する方法はありますか、それとも本当にすべてのレガシーコードを書き直す必要がありますか?

PHPの致命的なエラー:呼び出し時の参照渡しが30行目で削除されました...

これは、変数がコード全体の参照として関数に渡されるときに、どこでも発生します。


回答:


344

関数の定義では、実際の呼び出しではなく、参照によって呼び出しを示す必要があります。PHPはバージョン5.3で非推奨のエラーを表示し始めたので、コードを書き直すことをお勧めします。

ドキュメントから

関数呼び出しには参照記号がなく、関数定義にのみあります。関数定義だけで、参照によって引数を正しく渡すのに十分です。PHP 5.3.0の時点で、あなたが使用する場合、「コール・タイム・参照渡し」が廃止されていることを言って警告を取得します&ではfoo(&$a);

たとえば、次を使用する代わりに:

// Wrong way!
myFunc(&$arg);               # Deprecated pass-by-reference argument
function myFunc($arg) { }

使用する:

// Right way!
myFunc($var);                # pass-by-value argument
function myFunc(&$arg) { }

9
廃止予定はPHP 5.0.0以降です。そのE_COMPILE_WARNINGため、参考のためにレベルエラーが発生します。php.net
en

5
このエラーが発生しましたが、変数への追加を削除する必要がありました。
ダイアナ

2
これをイベント(&$ event)というオブジェクトの古いコードで使用し、エラーメッセージが消えるようにアンパサンドを削除する必要がありました。
ナタリア

1
開発者としての私のすべての年の間、私は実際に&phpを使う必要はありませんでした。決して。これはまさに私が探していたものでした。素晴らしい
フアン・ビラー

8
コメント内の人々は、&を削除すると予期しない結果が生じる可能性があることに注意してください。変数への変更は共有されなくなり、関数のローカルスコープにのみ表示されます。したがって、コードが何をしているのかを知らない限り、&文字を削除するのではなく、上記のように修正することをお勧めします
xorinzor

8

私のように、巨大なレガシープロジェクトを5.6に更新する必要があるため、これを読んだ人のために:ここでの答えが指摘するように、迅速な修正はありません:問題の発生を手動で見つけて修正する必要があります。

プロジェクト内のすべての問題のある行を見つけるために見つけた最も便利な方法(本格的な静的コードアナライザーを使用する以外は、これは非常に正確ですが、エディターの正しい位置にすぐに移動する方法はわかりません) Visual Studio Codeを使用していました。これは、組み込みの素晴らしいPHPリンターと、正規表現による検索を可能にする検索機能を備えています。(もちろん、PHP lintingとRegex検索を実行するIDE /コードエディターを使用できます。)

この正規表現を使用する:

^(?!.*function).*(\&\$)

&$関数定義ではない行のみの出現をプロジェクト全体で検索できます。

これは依然として多くの誤検知を引き起こしますが、それは仕事をより簡単にします。

VSCodeの検索結果ブラウザを使用すると、問題のある行をウォークスルーして見つけるのが非常に簡単になります。各結果をクリックするだけで、リンターが赤の下線を引いている行を探します。修正が必要なもの。


1
これは私が探していたものです!
Sonny

4
私がこの目的のために使用しているより正確な正規表現:(?<!function)[:> ][a-zA-Z0-9_]+(?<!foreach|array)\s?\([^()]*&\$
Mojo

phpcsを使用するだけで、これが含まれているすべてのファイルが掘り下げられます。
トーマスチェン

6

PHPとリファレンスはやや直感的ではありません。適切な場所で適切に参照を使用すると、パフォーマンスが大幅に向上するか、非常に醜い回避策や異常なコードを回避できます。

次の場合、エラーが発生します。

 function f(&$v){$v = true;}
 f(&$v);

 function f($v){$v = true;}
 f(&$v);

これらは以下のルールに従うことができるので失敗する必要はありませんが、多くのレガシーの混乱を防ぐために削除または無効化されていることは間違いありません。

それらが機能した場合、どちらも参照への冗長な変換を含み、2番目はスコープ指定された包含変数への冗長な変換も含みます。

2つ目は、参照を処理することを目的としていないコードに参照を渡すことを可能にするために使用されていました。これは、保守性のために非常に醜いです。

これは何もしません:

 function f($v){$v = true;}
 $r = &$v;
 f($r);

具体的には、参照を要求していないため、参照を通常の変数に戻します。

これは動作します:

 function f(&$v){$v = true;}
 f($v);

これは、非参照を渡しているが参照が必要であることを示しているため、参照に変換します。

これが意味することは、参照が明示的に要求されていない関数に参照を渡すことができないということです。これは、PHPが型の受け渡しに厳密である数少ない領域の1つにすることです。

より動的な動作が必要な場合、これは機能します。

 function f(&$v){$v = true;}
 $v = array(false,false,false);
 $r = &$v[1];
 f($r);

ここでは、参照が必要であり、すでに参照があるため、そのままにしておきます。それは参照を連鎖させるかもしれませんが、私はこれを疑います。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.