エラーメッセージ「厳密な標準:変数のみを参照で渡す必要があります」


81
$el = array_shift($instance->find(..))

上記のコードはどういうわけか厳格な標準の警告を報告していますが、これは報告しません:

function get_arr(){
    return array(1, 2);
}
$el = array_shift(get_arr());

それで、とにかくいつ警告を報告しますか?


1
$ instance-> find(..)は何を返しますか?
シルバーライト

2
ここソリューションです: stackoverflow.com/questions/9848295/...
ajaristi

2番目の例(get_arr()関数)厳密な標準通知(テスト済みのPHP5.2およびPHP5.5)を生成するため、例(またはロジック)は質問の方向が間違っている可能性があると思います。
MrWhite 2014年

回答:


93

次のコードについて考えてみます。

error_reporting(E_STRICT);
class test {
    function test_arr(&$a) {
        var_dump($a);
    }
    function get_arr() {
        return array(1, 2);
    }
}

$t = new test;
$t->test_arr($t->get_arr());

これにより、次の出力が生成されます。

Strict Standards: Only variables should be passed by reference in `test.php` on line 14
array(2) {
  [0]=>
  int(1)
  [1]=>
  int(2)
}

理由?このtest::get_arr()メソッドは変数ではなく、厳密モードでは警告が生成されます。get_arr()メソッド配列値を返すため、この動作は非常に直感的でありません。

strictモードでこのエラーを回避するには、メソッドのシグネチャを変更して、参照を使用しないようにします。

function test_arr($a) {
    var_dump($a);
}

署名を変更することはできないarray_shiftため、中間変数を使用することもできます。

$inter = get_arr();
$el = array_shift($inter);

7
@ user198729:私も説明や修正を探していましたが、最初の項目にcurrent()を使用できることがわかりました。残念ながら、end()は「最後の要素への内部ポインタを進める」ため、最後まで機能しません。current(array_reverse(somefunction()))は機能します(はい、それはばかげています)
MSpreij 2011年

1
を使用currentすると、配列ポインタが最初の要素にあると想定されます。ほとんどの場合、これは有効な仮定ですが、注意が必要です。
cmbuckley 2013

1
@leepowersもちろん、array_shift()参照が変更されることを期待しているのと同じ問題があります:-)
cmbuckley 2013

1
@ user198729$intermediate余分な括弧のペアを使用すると、値を回避できます。$el = array_shift( ( get_arr() ) );stackoverflow.com/questions/9848295/を
Chloe

1
@Chloeこれは、コードをシンプルに保つために私が見た中で最も素晴らしいソリューションです!! ありがとうございました!
hargobind 2016

7

$instance->find() 変数への参照を返します。

この参照を関数の引数として使用しようとすると、最初に変数に格納せずにレポートを取得します。

これはメモリリークの防止に役立ち、次のPHPバージョンではおそらくエラーになります。

2番目のコードブロックは、次のように記述した場合にエラーをスローします(&関数シグネチャのに注意してください)。

function &get_arr(){
    return array(1, 2);
}
$el = array_shift(get_arr());

したがって、迅速な(そしてそれほど良くない)修正は次のようになります:

$el = array_shift($tmp = $instance->find(..));

基本的に、最初に一時変数に割り当てを行い、その変数を引数として送信します。


これで動作するはずです(チェックしました)。参照を返すには、returnステートメントではなくメソッドシグネチャで宣言する必要があります(私のせいです)。
サギ2010年

いいえ、署名を変更できません。@ pygorex1の中間変数でこれを解決できますが、冗長に見えますね。
user198729 2010年

署名を変更できないことはわかっていますが、その方法を説明しただけです。あなたは持っている一時的な(=中間)変数を使用していますが、同じ行でそれを行うことができます。2番目のコードスニペットを見てください。
サギ2010年

4
2番目のスニペットを試しましたが、機能しません。別の行でのみ機能します
user198729 2010年

3
確かに。割り当ては、割り当てられた値を返しますarray_shift($tmp = $instance->find(..))割り当ての値$instance->find(..)$tmpした後、通過割り当ての値array_shift()-渡すのと同じものではない$tmp自体が、これは良い割り当てずに、元の状況よりもありません。
phils 2014

6

エラーの原因は、内部PHPプログラミングデータ構造関数array_shift()[php.net/end]の使用です。

この関数は、配列をパラメーターとして受け取ります。アンパサンドはarray_shift()マニュアルのプロトタイプに示されていますが」、その関数の拡張定義に続く注意文書はなく、パラメータが実際に参照によって渡されるという明確な説明もありません。

おそらくこれは/ understanded /です。しかし、理解できなかったため、エラーの原因を特定することが困難でした。

コードを再現する:

function get_arr()
{
    return array(1, 2);
}
$array = get_arr();
$el = array_shift($array);

3

このコード:

$monthly_index = array_shift(unpack('H*', date('m/Y')));

次のように変更する必要があります。

$date_time = date('m/Y');
$unpack = unpack('H*', $date_time);
array_shift($unpack);


0

そうですね、そのような明らかなケースでは、関数の前に「@」を使用することで、いつでもPHPにメッセージを抑制するように指示できます。

$monthly_index = @array_shift(unpack('H*', date('m/Y')));

すべてを抑制することは、最良のプログラミング手法の1つではない可能性がありますこの方法でエラーが、特定の場合(このような場合)には便利で許容範囲内です。

結果として、あなたの友人の「システム管理者」は、汚染が少ないことに満足すると確信していますerror.log


誰がこの回答に反対票を投じたかはわかりませんが、提示されたソリューションは機能し、PHPの標準的な手法です。本当にがっかり...次回はもう質問に答えられないかもしれません... :(
Julio Marchi 2016

5
エラーメッセージを抑制してもコードの問題が解決しないためだと思います。このタイプのエラーが将来のPHPリリースでE_STRICTからE_ERRORに変更され、コードが実行されず、エラー/出力も生成されない場合はどうしますか?
ルーク

@TinoDidriksen、私は、特に新世代のために、いくつかの「悪い習慣」に対して助言する理由を理解し、同意します。ただし、リソースは、安全に使用でき、提案されたコンテキストに適用できる場合に使用する必要があります。エラーサプレッサー「@」が廃止された場合、言語自体から削除されます。「eval」と同じです(悪かもしれませんが、目的があります)。私が反対しているのは、いくつかのリソースの使用ではなく、アドバイスの一般化です。特に提案されたケースでは、デバッグ目的であっても、それを使用しても害はありません。
Julio Marchi 2017
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.