PHP7対応

  • ページ: BugTrack2
  • 投稿者: umorigu
  • 優先順位: 重要
  • 状態: 完了
  • カテゴリー: 本体新機能
  • 投稿日: 2016-01-03 (日) 07:32:46
  • バージョン: 1.5.0
  • リリース予定バージョン: 1.5.1

メッセージ

2015/12/03 に PHP7 が リリースされました。 php.net:archive/2015.php

2016-01-03時点の最新版である PukiWiki 1.5.0 は PHP7 で動作しないので修正が必要です。


PukiWiki 1.5.0 を PHP7 で動作させたときの表示:

Parse error: syntax error, unexpected 'new' (T_NEW) in C:\d\p7\lib\func.php on line 531

関連情報:

分かっている問題:

  • 1. 新しいオブジェクトを参照渡しで代入できない - 「new 文の結果を参照渡しで変数に代入することができなくなりました。」
  • 2. 変更された関数 - preg_replace() 関数が "\e" (PREG_REPLACE_EVAL) をサポートしなくなりました。
    • php.net:manual/ja/migration70.changed-functions.php#migration70.changed-functions.core
    • 注釈の抽出に $NotePattern (lib/html.php, lib/init.php) で利用されている
    • 同一個所のバグ: BugTrack2/22 見出しと目次に含まれる注釈の構文定義の揺れ (正規表現のパッチ)
    • 同一個所のバグ2: BugTrack2/358 XAMPPの特定バージョンで「テキスト整形のルール」 FormattingRules を表示できない
    • 対策: /e を使わなくしました。(もともと PREG_REPLACE_EVAL のロジックは使っていなかったので、単純に実装上から e を削除しただけです)
  • 3. navi.inc.php のNextリンクが不正。リンク先がparentと同じになっている
    • foreach の変更 - 「foreach は内部の配列ポインタを変更しない」
    • php.net:manual/ja/migration70.incompatible.php#migration70.incompatible.foreach.array-pointer
    • arrayの内部ポインタの挙動の違いによるもの (current関数)
      • 参考リンク: wiki.php.net/rfc/php7_foreach qiita.com/hnw/items/c79458dead338a554a13
    • 対策: 配列の内部変数に依存しないロジックに書き換えた。current以外の配列内部ポインタ参照関数を利用していないことを確認した
  • 4. ereg系正規表現関数がなくなった

コメント: & new Class()

  • & new Class() の構文がサポートされなくなったようなので、PHP4との両対応が難しくなっています -- umorigu 2016-01-03 (日) 07:35:26
    • ふむ・・・ Deprecated になったといういう記載は無さそうですね -- henoheno 2016-01-05 (火) 21:33:02
    • ここのようです。 php.net:manual/ja/migration70.incompatible.php#migration70.incompatible.other.new-by-ref PHP 5.6.x から PHP 7.0.x への移行 - 下位互換性のないその他の変更 - 新しいオブジェクトを参照渡しで代入できない - 「new 文の結果を参照渡しで変数に代入することができなくなりました。」 -- umorigu 2016-01-05 (火) 23:36:57
  • '& new Class' を 'new Class' に変えるだけで PHP7 でも動作するようになりました。 sfjp:projects/pukiwiki/scm/git/pukiwiki/commits/b1489f40b55e74dec22f0066bfb07bf1e835132c PHP4でも動作しているように見えるのですが、問題があることをどうやって確認しよう・・・ -- umorigu 2016-01-06 (水) 01:06:38
    • officialとdevのデータをPHP4.1と7で表示してみて差分をとる方法を考えました -- umorigu 2016-01-06 (水) 01:42:52
  • 新しいオブジェクトを参照渡しで代入できない は、BugTrack2/146みたく結果をバッファに入れてからなら参照渡しできるのかな?と思ったけど、php.net:manual/language.operators.assignment.phpからするとPHP4だけ最初は丸々コピーされる状況がリビジョン:b1489f40b55e74dec22f0066bfb07bf1e835132c と変わらない気がするので意味ないかな~と思い直す…(お役に立てなさそうだ…) -- 2016-01-07 (木) 20:03:47
    • 情報ありがとうございます。BugTrack2/146 ここで & new Class() が一気に増えたんですね。必要があって参照にしているんだと思っていましたが、経緯を見ると E_NOTICE を避けるために導入されたようです。今はもうE_NOTICE上等なので無視するとして、これなら機能的な問題も起きなさそうです。大変参考になりました -- umorigu 2016-01-08 (金) 01:40:59
    • 参照返しでの"return new Class()"に関するBugTrack2/146のコミット cvs:lib/convert_html.php (1.17) は物理的に消えている(teananさんのコメント 2005-12-29 (木) 23:23:33 からのやりとりを参照)らしいですよ。"& new Class()"という使い方は、BugTrack/499あたりの改修(GITだとpukiwiki/commits/8187d3406d0ebfbd2067a8b3ff74411190767b68)の時点でも存在はしているようです。 -- 2016-01-08 (金) 21:48:49
    • 早とちりしました。今のところ問題ないので結果オーライということで・・・ -- umorigu 2016-01-11 (月) 00:15:12
  • なるほど "&" が目に入っていませんでした。
    • PHP4においてオブジェクトを代入した際の挙動はいわゆる deep copy であって、shallow copy するためには 参照渡しを明示しなければならなかった
    • PHP5からはオブジェクトを代入した際の挙動が shallow copy に変わり、deep copy するためにはオブジェクト毎に clone しなければならなくなった。参照渡しは Deprecated となった
    • PHP7では class の参照渡しの記法自体が禁じられた。 (状況的に、newの)参照渡しは構文エラーとなった
      • もしかすると少し誤解があるかもしれません。PHP7でもオブジェクトへの参照が禁止されたわけではありません。new の前に & が書けなくなっただけです。PHP4と5以降で違いがあるのはnewの挙動です。PHP4「newでオブジェトの実体が返る」PHP5「newでオブジェクトの実体を指すポインタが返る」。単純にnewした結果を代入するとdeep copyになったりshallow copyになったりするのは、newの挙動が変わった結果として表れている現象と言えるでしょうか。一方、参照の代入 ( $a =& $b ) は右辺の変数の参照を代入するものであり、つまりPHP5以降は = & new Class は(右辺に変数がないので)意味がなかったのを、PHP4との互換性のために無理やり = new Class と同じ挙動(オブジェクトの実体を指すポインタを返す)に読み替えていた、ということのようです。PHP7ではこの「無意味な記法」ができなくなった、ということだと理解しています -- umorigu 2016-01-10 (日) 23:30:31
    • このような状況で、仮にPHP4のコードをPHP7的に直すのであれば、参照渡しのコードを残すことができないみたいですから、副作用は 「PHP4環境で実行した場合に、shallow copy のつもりで書いた代入が deep copy になる」ことです。変更したはずの値が先祖返りしたり、オーバーヘッド(メモリ、CPU、処理時間)が増加することが予想されます。前者については、とある変数に代入したオブジェクトを、別の変数に代入した上で、どちらの変数も使い続けるようなシチュエーションでもなければその状況にはならないでしょう。後者はどうしようもないですね。 -- henoheno 2016-01-07 (木) 23:22:50
    • なので例えば lib/config.php で umorigu さんが変更された部分は、変数 $obj を、オブジェクトを収める唯一の器として使い回しているだけですから、前者の(=機能上の)影響はないでしょう。 -- henoheno 2016-01-07 (木) 23:33:39
      • 「とある変数に代入したオブジェクトを、別の変数に代入した上で、どちらの変数も使い続けるようなシチュエーションでもなければその状況にはならないでしょう」コメントありがとうございます。まさにご指摘の通りで、newの挙動の違いがあってもPHP4で最終的に出力結果が変わらないことを実データによって確認できたので、この点について対応済みとしたく思います -- umorigu 2016-01-10 (日) 23:42:56
  • ちなみに $obj = new Class() した後に、 $obj2 = & $obj (参照渡し)することはできるのでしょうか?今手元にPHP7はありません。 -- henoheno 2016-01-07 (木) 23:49:10
    • オブジェクトの参照の代入はできるようです -- umorigu 2016-01-08 (金) 01:36:00
      class C { var $v; function __construct($_v) { $this->v = $_v; } }
      $a = new C(1);
      $b = new C(3);
      echo $a->v; // => 1
      echo $b->v; // => 3
      $ref_a = &$a;
      $ref_a = $b;
      echo $a->v; // => 3
      echo $b->v; // => 3
      $ref_a->v = 5;
      echo $a->v; // => 5
      echo $b->v; // => 5
      $b->v = 7;
      echo $a->v; // => 7
      echo $b->v; // => 7
    • 確認をありがとうございました。オブジェクトの参照渡し自体は可能であるならば、一応shallow copyの余地はありそうですね。 -- henoheno 2016-01-11 (月) 03:05:39
  • そもそも参照渡ししている理由は何でしょうか。PHPではポインタが使え無いので実質ポインタっぽくなっていますがポインタではありません。リソース節約的意味ならほぼ意味ありませんよ -- [[.]] 2016-01-15 (金) 09:13:10
    • 過去の実装なので推測するしかないのですが、PHP4とPHP5の挙動を合わせたかったのだと思います。『$c = &new C』と書いておけば、PHP4とPHP5のどちらで実行しても、PHP5で『$c = new C』と書いたのと同じ動作(オブジェクトの実体への参照が$cに代入される)になっていました -- umorigu 2016-01-16 (土) 15:15:06

コメント

  • 正直、今回のPHP7は今までの流れから大きく方向転換してイマドキの設計思想を採用しています。PHP4と完全互換で同一スクリプトというのは難しいのではないでしょうか -- NoName? 2016-01-07 (木) 11:29:48
  • なので、PHP4や古い環境向けのバグFIXのみを1.5系に残しつつ1.5系からPHP7に最適化した1.6系を作ったほうが早い気がします。 -- NoName? 2016-01-07 (木) 11:31:57
    • 昨日まで私もそう("PHP4と完全互換で同一スクリプトというのは難しい")思ってたのですが、少しの変更で動作してしまったのでこのままPHP4,PHP5.x,PHP7 対応にできそうだな、と思ってます。ただPHP4で動作を見るのは次のバージョンまでにします。もう使ってる人も少ないでしょう。次の次は 5.2 or 5.3 あたりを最低ラインにしようかなと。5.3 がトップシェアになったというニュースもありますね :-) w3techs.com/blog/entry/php_version_5_3_is_now_the_most_used_version_just_ahead_of_5_2 -- umorigu 2016-01-08 (金) 01:08:27
  • PHP7 で PukiWiki officialdev のデータはすべて表示できる程度に対応しました。 branch_r1_5 -- umorigu 2016-01-10 (日) 18:33:31
  • branch_r1_5ブランチのHEADではPHP7で動作するようになりました。これをもってPHP7対応完了とします。この変更は次回リリース1.5.1に含まれます。PHP7上で問題を見つけた方は、ここへのコメントか、新規BugTrackの登録にてお知らせください -- umorigu 2016-01-10 (日) 23:58:37
  • &だけ対応しましたが、#contentsが使えないみたいです。 -- nobou? 2016-01-15 (金) 17:01:34
    • #contents の見出しリストが正しく表示されないのは「2. 変更された関数 - preg_replace() 関数が "\e" (PREG_REPLACE_EVAL) をサポートしなくなりました。」が原因です。1.5.0をPHP7で動作させるためには branch_r1_5の "1746320 Merge branch 'php7' into branch_r1_5" でマージされている5つの変更が必要です -- umorigu 2016-01-16 (土) 14:42:56
      • すいません、コメントの5つの変更が追えないのですが、サマリにある4項目の修正でOKでしょうか。 -- elem? 2016-11-19 (土) 16:55:32
      • 4項目が5つに分割されてコミットされている(=5つの変更)ということだと思います。5つの変更をすべてまとめたのが ja.osdn.net:projects/pukiwiki/scm/git/pukiwiki/commits/1746320f9b855bba054dfbdb2bc868824cc4296c で、これを参考に修正するといいかと。 -- bee 2016-11-19 (土) 18:58:39
      • はい。それでOKです。 df0569a 6ac4ecf 51ce191 59f8641 b1489f4 -- umorigu 2016-11-19 (土) 19:07:51
        $ git log --oneline --graph --decorate 1746320
        *   1746320 Merge branch 'php7' into branch_r1_5
        |\
        | * df0569a BugTrack2/369 PHP7: Replace ereg regex functions with preg_xxx
        | * 6ac4ecf BugTrack2/369 Follow PHP7 changes of internal array pointer
        | * 51ce191 BugTrack2/369 PHP7 - Remove /e (PREG_REPLACE_EVAL) in preg_replace
        | * 59f8641 Fix invalid reference operator of array for usort
        | * b1489f4 BugTrack2/369 Support PHP7 - Remove '& new Class' notation
        |/
        * 4752aff BugTrack2/358 Improve note regex for better PHP compatibility


トップ   編集 凍結 差分 バックアップ 添付 複製 名前変更 リロード   新規 一覧 検索 最終更新   ヘルプ   最終更新のRSS
Last-modified: 2016-11-19 (土) 19:18:20
Site admin: PukiWiki Development Team

PukiWiki 1.5.2+ © 2001-2019 PukiWiki Development Team. Powered by PHP 5.6.40-0+deb8u7. HTML convert time: 0.546 sec.

OSDN