こんにちは。リスペクトの木村です。
12月3日に、やっとPHP7からRCが外れましたがいかがお過ごしでしょうか。
そんな私は、PHP5.4のサポートが今年の9月4日の5.4.45リリースで終わっているというのについ最近気付きました。
そんな今回は、CakePHPの各バージョン(3.x/2.x/1.3)がPHP7上で正しく動作するのか?を検証してみた、という話をお届けします。
検証環境
- CentOS 7.1.1503
- Apache 2.4.6
- PHP 7.0.0
- MySQL 5.7.9
ApacheはCentOSのリポジトリ、PHPはremi、MySQLは公式のyumリポジトリから入れています。
利用したバージョン
それぞれの系列の、2015/12/07時点での最新版を利用します。
ちなみに、1.3.21はリリースノートにもあるように1.3系の最終リリースとなっています。
1.3系の初回リリースから5年が経過していたり、3系のリリースが行われたというのが主な理由のようで、これ以降はセキュリティアップデートも行われないので注意が必要です。
必須条件
もちろんバージョンによって動作に必要な条件は全て違います。
とはいえ、元々そこまで厳しいわけでは無いので、比較的容易に準備する事ができます。
- 3.x
- PHP 5.4.16以上
- intl/mbstring extension
- MySQL(5.1.10以上)/PostgreSQL/SQLServer(2008以上)/SQLite 3
- 2.x
- PHP 5.3.0以上
- 2.6までは5.2.8以上
- MySQL(4以上)/PostgreSQL/SQLServer/SQLite
- PHP 5.3.0以上
- 1.3
- PHP 4.3.2以上
- MySQL(4以上)/PostgreSQL/SQLServer/Oracle/SQLite
今回用意した環境は拡張も含めて全て要件を満たしています。
設置
改めて確認してみると、バージョンが新しくなるにつれ入れ方も変わってきていました。
- 3.x
- Composer経由のみ
- $ composer create-project –prefer-dist cakephp/app [app_name]
- 設置する過程で、パーミッションの設定や、Security.saltの書き換えもやってくれます。
- Composer経由のみ
- 2.x
- アーカイブのダウンロードに加えて、PEARやComposerを利用した設置も可能。
- 1.3
- アーカイブをダウンロードして展開するのみ。
今回は、各環境をDOCUMENT_ROOT下にフォルダ毎に分けて配置しました。
その後は、全環境でデータベース接続の設定と、2.xと1.3はtmpディレクトリ以下のパーミッション設定やSecurity回りの値の変更を行っています。
動作確認する
準備もできた所で、早速アクセスしてみます。
CakePHP 3.x
無事に動きました。
DBにも無事に接続できているようです。
CakePHP 2.x
こちらも無事に動きました。
DebugKitが入ってないのはさておき、DBにも接続できています。
CakePHP 1.3
先ほどまでとは打って変わって、いきなりのエラーです。
どうやらコアファイルに問題がある模様・・・。
対象のファイルの指定された行のあたりを見てみるとこんな感じでした。
/** * Gets a reference to the Inflector object instance * * @return object * @access public */ function &getInstance() { static $instance = array(); if (!$instance) { $instance[0] =& new Inflector(); } return $instance[0]; }
$instance[0] =& new Inflector();
でエラーになっています。
PHP5でnewがリファレンスを返すようになったので、newの時に=&
を使うのは非推奨になりました。
PHP5だとE_DEPRECATEDやE_STRICTのエラーになっていたので設定によっては抑制できたのですが、PHP7で文法的に無効になったので、Parse Errorになっています。
(詳しくはこちら)
という訳なので、コアファイル内に大量に存在するであろう=&
を潰していきます。
たまに、$instance[0] = & new $class();
のように若干ズレた書き方をしている場合があるので要注意です。
ある程度置換した所で再度表示させてみると、またもやエラーです。
今度のエラーは、PHP7からstringが予約語に加わったので、その辺でエラーになっています。
(他に追加された予約後はこちら)
確かに指定されたファイルを見るとStringというそのままのクラスがあるので、これをCakeStringとしておき、ファイル名も「cake_string.php」にします。
あとは、class_exists('String')
やApp::import('Core', 'String')
している部分を、それぞれclass_exists('CakeString')
やApp::import('Core', 'CakeString')
に書き直したり、Stringクラスをstaticで呼んでいる部分をCakeStringを呼ぶようにすると、表示されるようになりました。
一番上のwarningは、SessionHelper::write()の継承元であるCakeSession::write()と引数の数が合ってないためwarningになっています。
SessionHelper::write()の引数を継承元と同じにすると、warningも消えました。
DBには接続できていますが、まともに動作させるには結構修正しなけれなならない部分が多い予感がします。
(今回はコアをいじる事で何とか動くようにはなりましたが。)
ちなみに、コアを眺めている中でif (PHP5) {~} else {~}
というif文でバージョン別分岐をしている部分がありましたが、define('PHP5', (PHP_VERSION >= 5));
という感じで定義されていたので、PHP7でもPHP5以降という扱いになりそうです。
検証まとめ
- 3系と2系はとりあえず大丈夫そうでした。
- 1.3(以前も)はそのままだともはや厳しそうです。
- コアを書き換えれば何とか動作しますが、何があるか分からないので、大人しく2.xか3.xへアップグレードしましょう。
おわりに
という訳で、PHP7でCakePHPが動くかどうか検証してみました。
1.3は動かなくて、3.xはばっちり(PHP7向けの修正が最新版でされていたので)、2.xは動くか微妙だなと思っていたのですが、とりあえずサポートされているバージョンは動作してくれました。
ただ、コア部分が動作するという所まで見ているので、個々の実装によっては何かしらの作業は必要になってくるのではないかと思います。
PHP7はリリースされたばかりという事もありまだまだ普及には時間がかかりそうですが、もし移行する事になった場合の計画作成の参考にでもなれば幸いです。
現場からは以上です。