web-dev-qa-db-ja.com

参照によって渡すことができるのは変数のみです

私はうさぎの穴を案内するカスタムエラーハンドラーを使用するという明るい考えを持っていました。

次のコードは、(カスタムエラーハンドラーの有無にかかわらず)与えます:致命的なエラー:変数は参照でのみ渡すことができます

function foo(){
    $b=array_pop(array("a","b","c"));
    return $b;
}
print_r(foo());

次のコードは、(カスタムエラーハンドラーのみ)を示します。(2048)変数のみを参照渡しする必要があります

function foo(){
    $a=explode( '/' , 'a/b/c');
    $c=array_pop(array_slice($a,-2,1));
    return $c;
}
print_r(foo());

2つ目は、「コンパクト」なコードがたくさんあるので心配です。そのため、カスタムログハンドラーを使用するという優れたアイデア(ロギングモジュールを改善するため)を捨てるか、すべてのコードを拡張します。

より良いアイデアを持つ人はいますか?また、WTF?

[〜#〜]更新[〜#〜]

回答のおかげで、phpがエラー処理を行う方法について何かを学びました。 E_STRICT(php 5)を含まないE_ALLの混乱はクールではありません。

さらに、独自のカスタムエラーハンドラーを作成すると、デフォルトでE_STRICTが有効になり、問題が発生します。

ストーリーの教訓は、独自のエラーハンドラーを使用してそれらすべてをキャッチし、エラー定数(E_STRICT、E_USER_WARNING、E_USER_ERRORなど)を使用してフィルタリングを行うことです。

変数参照と特定の関数での「メモリ破損の問題」については、何と言えますか?二重に涼しくない。私は(そうする必要があるという意味ではありません)、エラーハンドラーでE_STRICTを無視します。

18
zaf

array_pop()は、パラメーターとして渡された値を変更しようとします。 2番目の例では、これはarray_slice()からの戻り値です。エンジン用語では、これは「一時的な値」であり、そのような値を参照で渡すことはできません。必要なのは一時変数です:

function foo(){
    $a=explode( '/' , 'a/b/c');
    $b=array_slice($a,-2,1);
    $c=array_pop($b);
    return $c;
}
print_r(foo());

次に、$ bへの参照をarray_pop()に渡すことができます。リファレンスの詳細については http://php.net/references を参照してください。

18
johannes

Php-cliで2番目のphpコードスニペットを試すと、次のようになりますerror_reportingをE_ALL | E_STRICTに設定した後

    gparis@techosaure:~/workspace/universcine.com$ php -a
Interactive Shell

php > function foo(){
php {     $a=explode( '/' , 'a/b/c');
php {     $c=array_pop(array_slice($a,-2,1));
php {     return $c;
php { }
php > print_r(foo());
PHP Strict standards:  Only variables should be passed by reference in php Shell code on line 3
PHP Stack trace:
PHP   1. {main}() php Shell code:0
PHP   2. foo() php Shell code:1

ご覧のとおり、これは厳密な基準にすぎません。また、カスタムエラーハンドラーにそれらを無視させることも簡単にできます(取得する値に基づいて、ここでは2048など)。

PHP 5.3以降、E_ALLにはE_STRICTが含まれていません。これを見てください。

php > foreach(array("E_ALL", "E_DEPRECATED", "E_STRICT", "E_NOTICE", "E_PARSE", "E_WARNING") as $const) echo $const . "  :\t" . constant($const) ."\t". decbin(constant($const)). "\n";
E_ALL  :        30719   111011111111111
E_DEPRECATED  : 8192     10000000000000
E_STRICT  :     2048       100000000000
E_NOTICE  :     8                  1000
E_PARSE  :      4                   100
E_WARNING  :    2                    10

PHP 5.4以降、E_ALLにはE_STRICTが含まれます。

E_ALL  :            32767   111111111111111
E_DEPRECATED  :     8192     10000000000000
E_STRICT  :         2048       100000000000
E_NOTICE  :         8                  1000
E_PARSE  :          4                   100
E_WARNING  :        2                    10
9
greg0ire

これはメモリ破壊の問題です(PHP開発チームによると)。割り当てを投入するだけです:

function foo(){
    $b = array_pop($arr = array("a","b","c"));
    return $b;
}
print_r(foo());

function foo(){
    $a = explode( '/' , 'a/b/c');
    $c = array_pop($arr = array_slice($a,-2,1));
    return $c;
}
print_r(foo());

2番目はE_STRICTを生成します。必要に応じて(これらの関数を変更したくない場合)、エラーハンドラーで異なる方法で処理できます。

4
webbiedave

array_pop()は、エラーが発生した場所に渡された値を変更します。機能は変更できません。つまり、最初に配列を変数に割り当て(参照: manual )、次にarray_pop()を実行する必要があります。

必要なコードはこれです:

_function foo(){
    $a = array("a","b","c");
    $b = array_pop($a);
    return $b;
}
_

編集:あなたが言及した両方の関数には同じ問題があります。配列を変数に割り当て、変数をarray_pop()に渡します。

1
Joseph

私は今(php 5以降)それは次のようになるはずだと思います:

function &foo(){ //NOTICE THE &
    $b=array_pop(array("a","b","c"));
    return $b;
}
print_r(foo());

そして

function &foo(){ //NOTICE THE &
    $a=explode( '/' , 'a/b/c');
    $c=array_pop(array_slice($a, $b = -2, $c = 1)); //NOW NO DIRECT VALUES ARE PASSED IT MUST BE VARIABLES
    return $c;
}
print_r(foo());

しかし、私はただの初心者です:)

1
popeyems
0
broadband

これを試して:

function foo(){
    $a = array("a","b","c");
    $b = array_pop($a);
    return $b;
}
0
baloo