16746


「PHP 5.6.11」で動作していた以下のようなソースが「PHP 7.1.0-dev」 で動作しなくなっていました。  
※switch文の「return AAAA::$z[0]($x, $y, $z);」で「Fatal error: Uncaught Error:
Access to undeclared static property: AAAA::$z in test.php:21」と表示されます。  
「return call_user_func_array( array('AAAA', $z[0]), array(&$x,$y,$z) );」
と書き換えれば動作することを確認はしていますが、  
PHP7にバージョンアップにするにあたって、違う点などを調べたのですが、英語が苦手なのもあって、この変更点に関する記述がわかりませんでした。  
どなたがご存知でしたら、参考URLなど教えていただけませんでしょうか？

[code]

    class AAAA {
     static function caller(&$x, $y, $z)
     {
      switch($z[0])
      {
        case 'caller':
          return 0;
        case 'abc':
          return AAAA::aaa($x, $y, $z);
        case 'def':
          return AAAA::bbb($x, $y, $z);
        default:
          if( strlen($z[0]) )
          {
            return AAAA::$z[0]($x, $y, $z);
          }
          else { return 0; }
      }
     }
    
     static function aaa(&$x, $y, $z)
     {
       return $x[0] + $y[0];
     }
    
     static function bbb(&$x, $y, $z)
     {
       return $x[1] + $y[1];
     }
    
     static function func1(&$x, $y, $z)
     {
       $a = $x[0] + $z[1];
       $b = $y[0] * $z[1];
       return $a * $b;
     }
    
     static function func2(&$x, $y, $z)
     {
       $a = $x[1] + $z[2];
       $b = $y[1] * $z[3];
       return $a * $b;
     }
    }
    
    $a = array(1,2,3,4);
    $b = array(5,6,7,8);
    $c = array('func2', 3,4,5);
    $rec = AAAA::caller($a, $b, $c);
    var_dump($rec);
    
[/code]


CC BY-SA 3.0
2015-09-18T06:59:54.020
16740
2015-09-18T09:03:43.930
9128
question
php
PHP7 クラス内の関数呼び出し


その挙動の違いは、パーサーの仕様変更によるものです。

`AAAA::$z[0]()` と書いた場合、これまでのPHPでは `$z[0]` を優先して解釈していました。

  1. まず `$z[0]` を評価する
  2. その名前の静的メソッドをクラス `AAAA` から探して呼び出す

これが PHP7 では左結合、つまり `AAAA::$z` を優先するようになりました。

  1. まず `AAAA::$z` を評価する
  2. その最初の要素 `[0]` を取り出す
  3. その名前の関数を探して呼び出す

このため、「静的プロパティ `AAAA::$z` が見つからない」というエラーが出ています。

PHP 5.5.6 での例 <http://melpon.org/wandbox/permlink/uzNOlxho3XMslK3R>  
PHP 7.1.0-dev での例 <http://melpon.org/wandbox/permlink/fd7HAW5kaOGHyLah>

`$z[0]` を波括弧で囲んで `AAAA::{$z[0]}()` とすることで、これまでの挙動を再現できます。

詳しくはマニュアルの移行ガイドをご覧ください。

  * [PHP: PHP 5.6.x から PHP 7.0.x への移行 - Manual](http://php.net/manual/ja/migration70.php)
  * 同、「下位互換性のない変更点」より[「変数の取り扱いの変更」](http://php.net/manual/ja/migration70.incompatible.php#migration70.incompatible.variable-handling.indirect)


CC BY-SA 3.0
2015-09-18T09:03:43.930
16746
2015-09-18T09:03:43.930
8000
16740
answer