PHP5.6からPHP7にアップグレードして実際にはまった点9個

仕事で使っているPHPアプリケーションをPHP7 beta1で動かしてみたらそのままでは動きませんでした。 私が実際にはまった点を紹介します。

なお、PHP7の変更点についてはhnwさんの記事に詳しく網羅されているのでご一読ください。

PHP7で変わること - hnwの日記

Apacheのモジュール名が変わっていた

ApacheにPHPを組み込むためのモジュール(俗にいうmod_php)のモジュール名・ファイル名が変更になっていました。

LoadModule php5_module modules/libphp5.so

LoadModule php7_module modules/libphp7.so

memcache extensionがインストールできない

PHPからMemcachedを使うためのExtensionには2つあります。

memcacheの方はビルドできませんでした。 一方、memcachedの方は Githubレポジトリのphp7ブランチを使えばビルドできました。

ビルド・インストールするには下記のようにします。

sudo yum install libmemcached-devel

cd /usr/local/src
git clone -b php7 --depth 1 https://github.com/php-memcached-dev/php-memcached
cd php-memcached
phpize
./configure
make
sudo make install

エクステンションをmemcacheからmemcachedに差し替える場合は影響範囲が広くなります。 memcacheのPHP7対応を待つという選択肢もありますが、いつかリリースされるという保証はありません。

imagickがインストールできない

pecl install imagickなどとしても無駄無駄ァでした。

これも、Githubのphpsevenブランチを取得してビルドしたらうまくいきました。

sudo yum install ImageMagick ImageMagick-devel

cd /usr/local/src
git clone -b phpseven --depth 1 https://github.com/mkoppanen/imagick

cd imagick
phpize
./configure
make
sudo make install

IntクラスやStringクラスがエラーに

class Int {}
class String {}

こういうクラス名がエラーになります。

PHP Fatal error:  Cannot use 'Int' as class name as it is reserved
PHP Fatal error:  Cannot use 'String' as class name as it is reserved

PHP7調査(34)型名と同じクラス名が作れないようになった

preg_replaceのe修飾子の挙動が変わる

  • PHP5.5からpreg_replaceのe修飾子はDEPRECATED扱いとなっていたが、一応動いてはいた。
  • PHP7では、preg_replaceのe修飾子を使うと、Warningを吐きつつNULLを返す。
  • PHP5.5時代にpreg_replaceに@を書いてお茶を濁した人は、PHP7で地雷を踏む。

関数のパラメータで同じ変数名を2回書いたらエラーに

(深遠な理由から)こういう関数を定義していたら、PHP5.6では問題なかったのですが、

function func($void = null, $void = null) {
    //$voidは関数内では一切使用しない
}

PHP7だとFatal Errorになりました。

PHP Fatal error:  Redefinition of parameter $void in /Users/DQNEO/a.php on line 6

同じ名前の変数をを2回定義できなくなったようです。 下記のようにして回避しました。

function func($void1 = null, $void2 = null) {
}

クラス名と同名のコンストラクタが非推奨に

こういうやつがDEPRECATEDになります。

class Pager
{
    function Pager(){}
}
PHP Deprecated:  Methods with the same name as their class will not be constructors in a future version of PHP; Pager has a deprecated constructor

PEAR系ライブラリのようにPHP4時代に作られたライブラリが軒並みこれに該当します。

class Pager
{
-    function Pager($options = array())
+    function __construct($options = array())

pg_field_type関数が激遅になっていた。

pg_field_typeというのは、PHPからPostgreSQLを使うときに、クエリの結果セットからカラムのデータ型を調べるときに使います。ORマッパの内部で使われていたりします。(INSERTする直前に対象テーブルの全カラムのデータ型を調べる等)

これはおそらくパフォーマンス劣化バグだと思われるので、正式版リリースまでに修正されることを待ちましょう。

もしくは、PHP本家にPull Requestを送るチャンスかもしれません・・・!

OSXで–with-pgsqlをつけるとコンパイルエラー

OSX(yosemite)で ./configure --with-pgsqlでビルドできませんでした。

undefined symbols for architecture x86_64:
"__emalloc_16", referenced from:
_zif_pg_lo_open in pgsql.o
__php_pgsql_notice_handler in pgsql.o
"__emalloc_24", referenced from:
_zif_pg_query in pgsql.o
_zif_pg_query_params in pgsql.o
_zif_pg_prepare in pgsql.o
_zif_pg_execute in pgsql.o
_zif_pg_get_result in pgsql.o
_zif_pg_insert in pgsql.o
"__emalloc_56", referenced from:
_php_pgsql_fetch_hash in pgsql.o
"_lo_lseek64", referenced from:
_zif_pg_lo_seek in pgsql.o
"_lo_tell64", referenced from:
_zif_pg_lo_tell in pgsql.o
"_lo_truncate64", referenced from:
_zif_pg_lo_truncate in pgsql.o
ld: symbol(s) not found for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)
make: *** [libs/libphp7.bundle] Error 1

解決方法がわからなかったのでいったん諦めました。 まあ本番はLinuxですしね… (あの葡萄はすっぱい的な)

まとめ

PHP7を導入してはまった点をまとめました。

逆に言うと、たったこれだけ直しただけで問題なく動きました。 メジャーバージョンアップのわりには後方互換はかなり保たれている印象です。

正式版のリリースは2015年10月だそうです。 待ち遠しいですね!

https://wiki.php.net/rfc/php7timeline

PHP++

カテゴリ: