PHP 5.5.x から PHP 5.6.x への移行　のまとめ


# PHP 5.5.x から PHP 5.6.x への移行　のまとめ

※PHPマニュアルの内容をまとめただけです。(勝手な感想も書いてますが・・・)

## 下位互換性のない変更点

<pre>
既存の PHP 5 のコードのほとんどは変更なしで動作するはずですが、 以下の下位互換性のない変更点については注意しましょう。
</pre>

### クラスのプロパティに設定した配列のキーが上書きされない

<pre>
以前のバージョンでは、クラスのプロパティとして宣言されている配列で明示的なキーと暗黙のキーが混在している場合に、
明示的に指定したキーと暗黙の数値キーが重複すると、黙って上書きされていました。
</pre>

勝手に何の警告もなく上書きされてたらしい。

```PHP:例
<?php
class C {
    const ONE = 1;
    public $array = [
        self::ONE => 'foo',
        'bar',
        'quux',
    ];
}

var_dump((new C)->array);
?>
```


```text:PHP5.5での出力
array(2) {
  [0]=>
  string(3) "bar"
  [1]=>
  string(4) "quux"
}
```

```text:PHP5.6での出力
array(3) {
  [1]=>
  string(3) "foo"
  [2]=>
  string(3) "bar"
  [3]=>
  string(4) "quux"
}
```

### json_decode()が、より厳格に

<pre>
json_decode() は、JSON リテラル true、false および null について、すべて小文字のものしか受け付けなくなりました。
これは、JSON の仕様に基づくものです。
小文字以外の場合は、json_last_error() にエラーが設定されます。
以前のバージョンの json_decode() は、大文字が混ざっているものでも受け付けていました。

この変更の影響を受けるのは、無効な形式の JSON を json_decode() に渡していた場合だけです。
妥当な形式の JSON は、この変更の影響を受けず、通常通りに処理されます。
</pre>

要は小文字使ってねってことですよね。

### ストリームラッパーが、SSL/TLSを使っている場合のピア証明書とホスト名の検証にデフォルトで対応

<pre>
暗号化されたすべてのクライアントストリームで、ピア検証がデフォルトで有効になりました。
デフォルトでは、OpenSSL のデフォルト CA バンドルを使ってピア証明書を検証します。
たいていの場合は、正しい SSL 証明書を持つサーバーと通信するならこれを変更する必要はありません。
OpenSSL が、よく知られた CA バンドルを使うように設定されているからです。

デフォルトの CA バンドルを上書きすることもできます。
openssl.cafile あるいは openssl.capath を設定するえばグローバルに変更でき、
コンテキストオプション cafile あるいは capath を使えばリクエスト単位で変更できます。

一般的にはおすすめできませんが、 certificate verification for a request by setting the コンテキストオプション verify_peer を
FALSE にしてリクエストでのピア証明書の検証を無効化することもできます。
また同じく、ピア名の検証も、コンテキストオプション verify_peer_name を FALSE にすれば無効化できます。
</pre>

ここらへんは疎いので、流す。

### GMPリソースがオブジェクトに

<pre>
GMP リソースがオブジェクトになりました。
GMP 拡張モジュールに実装されている API に変更はなく、コードに手を加えなくてもそのまま動作します。
しかし、is_resource() などでリソースかどうかを明示的に調べている場合は注意が必要です。
</pre>

注意が必要というか、リソースかどうかで判断してるんだから見直すべきなんじゃ。。。

### Mcrypt 関数は、有効なキーと IV を要求する

<pre>
mcrypt_encrypt()、mcrypt_decrypt()、mcrypt_cbc()、mcrypt_cfb()、mcrypt_ecb()、mcrypt_generic()、mcrypt_ofb()は、
無効なサイズのキーやIVを受け付けなくなりました。
IVが必要なブロック暗号化モードでIVが指定されていない場合にも、処理が失敗するようになりました。
</pre>

IV＝初期化ベクトル。
`mcrypt_cbc()` `mcrypt_cfb()` `mcrypt_ecb()` `mcrypt_ofb()`はPHP5.5以降は非推奨。

## 新機能

### 定数のスカラー式

<pre>
数値や文字列リテラルと定数を、これまでのバージョンでは静的な値が想定されていた場面
(定数やプロパティの宣言、関数のデフォルト引数など)で、スカラー式として扱えるようになりました。
</pre>

constでスカラー式使えるようになったのはかなり便利かも。

```PHP:例
<?php
const ONE = 1;
const TWO = ONE * 2;

class C {
    const THREE = TWO + 1;
    const ONE_THIRD = ONE / self::THREE;
    const SENTENCE = 'THREE の値は '.self::THREE;

    public function f($a = ONE + self::THREE) {
        return $a;
    }
}

echo (new C)->f()."\n";
echo C::SENTENCE;
?>
```

```text:出力結果
4
THREE の値は 3
```

### ... による可変個引数関数

<pre>
可変個引数の関数 の実装に ... 演算子が使えるようになり、 func_get_args() を使わずに済むようになりました。
</pre>

これは便利。
改修でメソッドのインタフェース変えないといけなくなりました！
とかなっても、可変になりそうなパラメータはあらかじめこうしとけばいい。
$paramに設定する順番はきちんと定めておかないとだけど。


```PHP:例
<?php
function f($req, $opt = null, ...$params) {
    // $params は配列で、残りのすべての引数が含まれます
    printf('$req: %d; $opt: %d; パラメータ数: %d'."\n",
           $req, $opt, count($params));
}

f(1);
f(1, 2);
f(1, 2, 3);
f(1, 2, 3, 4);
f(1, 2, 3, 4, 5);
?>
```

```text:出力結果
$req: 1; $opt: 0; パラメータ数: 0
$req: 1; $opt: 2; パラメータ数: 0
$req: 1; $opt: 2; パラメータ数: 1
$req: 1; $opt: 2; パラメータ数: 2
$req: 1; $opt: 2; パラメータ数: 3
```
わっかりにくい例だな。
一番上の例だと`$params=[]`
一番下の例だと`$params=[3,4,5]`
って感じになるのかな。

### ... による引数のアンパック

<pre>
配列 や Traversable オブジェクトを引数リストにアンパックするために、
関数の呼び出し時に ... 演算子が使えるようになりました。
これは、Ruby などの他の言語では splat 演算子と呼ばれることもあります。
</pre>

~~う～ん。
別にいらん。~~

```PHP:例
<?php
function add($a, $b, $c) {
    return $a + $b + $c;
}

$operators = [2, 3];
echo add(1, ...$operators);
?>
```

```text:出力結果
6
```

[2014/09/09 追記]
call_user_func_arrayの代わりとして使えそうです。

```PHP:5.6の機能
<?php
$args = array(1, 2);

$hoge = new Hoge();
$hoge->fuga(...$args);

class Hoge
{
    function fuga($a, $b)
    {
        echo $a + $b;
    }
}
?>
```

```PHP:call_user_func_array
<?php
$args = array(1, 2);

$hoge = new Hoge();
call_user_func_array(array($hoge, 'fuga'), $args);

class Hoge
{
    function fuga($a, $b)
    {
        echo $a + $b;
    }
}
?>
```

この２つは同じ。

### 累乗演算子 **

<pre>
右から評価する ** 演算子が追加されました。
これは累乗をサポートするものです。
さらに、短縮代入演算子 **= も追加されました。
</pre>

`$a = 2 * 2 * 2 * 2 * 2 * 2`とかしなくていいね。

```PHP:例
<?php
printf("2 ** 3 ==      %d\n", 2 ** 3);
printf("2 ** 3 ** 2 == %d\n", 2 ** 3 ** 2);

$a = 2;
$a **= 3;
printf("a ==           %d\n", $a);
?>
```

```text:出力結果
2 ** 3 ==      8
2 ** 3 ** 2 == 512
a ==           8
```

ちなみに`2 ** 3 ** 2`は右から評価されるので、
$2 **$ $3^2$
　↓
$2^9$
となる。

### use function および use const

<pre>
The use 演算子を拡張し、クラスだけではなく関数や定数もインポートできるようになりました。
それぞれ、言語構造 use function および use const を用います。
</pre>

ん。
使う場面あるのかな。よくわかんないや。

```PHP:例
<?php
namespace Name\Space {
    const FOO = 42;
    function f() { echo __FUNCTION__."\n"; }
}

namespace {
    use const Name\Space\FOO;
    use function Name\Space\f;

    echo FOO."\n";
    f();
}
?>
```

```text:出力結果
42
Name\Space\f
```

### phpdbg

<pre>
PHP now includes an interactive debugger called phpdbg implemented as a SAPI module.
詳細な情報は » phpdbg のドキュメント を参照ください。
</pre>

調べてみたところコマンドラインだけっぽい。
でも、新機能なのに説明手抜きすぎ。

### デフォルトの文字エンコーディング

<pre>
エンコーディングに依存する関数 htmlentities() や html_entity_decode() そして htmlspecialchars()
におけるデフォルトの文字セットとして、 default_charset を利用するようになりました。
iconv (非推奨) や mbstring でのエンコードが設定されている場合は、 default_charset よりもそちらのほうが優先されます。

この設定のデフォルト値は UTF-8 です。
</pre>

デフォルトがUTF-8に。
めでたしめでたし。

### php://input が再利用可能に

<pre>
php://input が再オープンできるようになり、必要に応じて何度でも読めるようになりました。
その結果として、POST されたデータを読むときに必要となるメモリの量が大幅に削減されました。
</pre>

使ったことないからとりあえず流しておく。

### 巨大なファイルのアップロード

<pre>
2ギガバイトより大きいサイズのファイルもアップロードできるようになりました。
</pre>

普通そんなサイズのアップロードしないんじゃないっすかね。

### GMP での演算子オーバーロードのサポート

<pre>
GMP オブジェクトが、 演算子のオーバーロードやスカラー型へのキャストに対応するようになりました。
GMP を使って、よりわかりやすいコードが書けるようになります。
</pre>

```PHP:例
<?php
$a = gmp_init(42);
$b = gmp_init(17);

// 5.6 より前のバージョンのコード
var_dump(gmp_add($a, $b));
var_dump(gmp_add($a, 17));
var_dump(gmp_add(42, $b));

// 5.6 以降の新しいコード
var_dump($a + $b);
var_dump($a + 17);
var_dump(42 + $b);
?>
```
見やすくなりましたね。

### hash_equals() による、タイミング攻撃に対応した文字列比較

<pre>
hash_equals() 関数が追加されました。 この関数は、二つの文字列の比較を一定の時間で行います。
タイミング攻撃を防ぐために、文字列の比較にはこの関数を使うべきです。
たとえば crypt() のパスワードハッシュをチェックしたりするときに使えます
(password_hash() や password_verify() が使えない場合を想定。これらの関数は、タイミング攻撃の影響を受けません)。
</pre>

セキュリティ強化ってところでしょうか。
ここはもう少し深く調べてみる。

```PHP:例
<?php
$expected  = crypt('12345', '$2a$07$usesomesillystringforsalt$');
$correct   = crypt('12345', '$2a$07$usesomesillystringforsalt$');
$incorrect = crypt('1234',  '$2a$07$usesomesillystringforsalt$');

var_dump(hash_equals($expected, $correct));
var_dump(hash_equals($expected, $incorrect));
?>
```

```text:出力結果
bool(true)
bool(false)
```

### __debugInfo()

<pre>
マジックメソッド __debugInfo() が追加されました。
var_dump() でオブジェクトの情報を出力する際の、 プロパティやその値の表示方法を変更できます。
</pre>

なるほど。

```PHP:例
<?php
class C {
    private $prop;

    public function __construct($val) {
        $this->prop = $val;
    }

    public function __debugInfo() {
        return [
            'propSquared' => $this->prop ** 2,
        ];
    }
}

var_dump(new C(42));
?>
```

```text:出力結果
object(C)#1 (1) {
  ["propSquared"]=>
  int(1764)
}
```

ちなみに`__debugInfo()`を使わなかった時は、すべての public, protected, private プロパティが表示される。

```PHP:例
<?php
class C {
    private   $privateVal;
    protected $protectedVal;
    public    $publicVal;

    public function __construct($val) {
        $this->privateVal   = $val;
        $this->protectedVal = $val;
        $this->publicVal    = $val;
    }
}

var_dump(new C(42));
?>
```

```text:出力結果
object(C)#1 (3) {
  ["privateVal:private"]=>
  int(42)
  ["protectedVal:protected"]=>
  int(42)
  ["publicVal"]=>
  int(42)
}
```

### gost-crypto ハッシュアルゴリズム

<pre>
ハッシュアルゴリズム gost-crypto が追加されました。
これは GOST ハッシュ関数を実装したもので、» RFC 4357, section 11.2に記載されている CryptoPro S-box テーブルを使っています。
</pre>

GOSTハッシュ関数というもの自体よくわからない。

### SSL/TLS の改良

<pre>
PHP 5.6 では、SSL/TLS のサポートに幅広い改良が加わりました。
ピア検証にデフォルトで対応したり、 証明書のフィンガープリントのマッチングに対応したり、
TLS 再ネゴシエーションアタックの対策をしたり、多数の SSL コンテキストオプションを新たに導入したりしました。
これらによって、暗号化されたストリームに関するよりきめ細やかな制御ができるようになりました。
</pre>

下記[PHP 5.6.x における OpenSSL 関連の変更](#2-6)を参照。

### pgsql の非同期サポート

<pre>
pgsql 拡張モジュールが、 非同期の接続や問い合わせに対応しました。
PostgreSQL データベースとのやりとりで、ノンブロッキング処理ができるようになります。
非同期接続を確立するには、定数 PGSQL_CONNECT_ASYNC を利用します。
そして、新しい関数 pg_connect_poll()、pg_socket()、 pg_consume_input()、pg_flush() を使って、非同期接続や問い合わせを処理します。
</pre>

なるほど。
あんまりイメージできてないけど、なんとなく。

## PHP 5.6.x で推奨されなくなる機能

### 非互換のコンテキストからの呼び出し

<pre>
非互換のコンテキストからのメソッド呼び出しが非推奨となり、 E_STRICT ではなく E_DEPRECATED が発生するようになりました。
この機能は、将来のバージョンの PHP で削除される予定です。
</pre>

```PHP:例
<?php
class A {
    function f() { echo get_class($this); }
}

class B {
    function f() { A::f(); }
}

(new B)->f();
?>
```

```text:出力結果
Deprecated: Non-static method A::f() should not be called statically, assuming $this from incompatible context in - on line 7
B
```

ちょっとよくわかんない。

### $HTTP_RAW_POST_DATA および always_populate_raw_post_data

<pre>
always_populate_raw_post_data を有効にすると、E_DEPRECATED が発生するようになりました。
新しいコードでは、$HTTP_RAW_POST_DATA ではなく php://input を使うようにしましょう。
$HTTP_RAW_POST_DATA は、将来のバージョンで削除される予定です。
この新しい振る舞い ($HTTP_RAW_POST_DATA が定義されていない状態) を試すには、 always_populate_raw_post_data に -1 を設定します。
</pre>

`php:input`使えってことですかね。

### iconv および mbstring のエンコーディング設定

<pre>
iconv および mbstring の、エンコーディングに関するオプションが非推奨となりました。
代わりに default_charset を使いましょう。
非推奨になったオプションは、以下のとおりです。

・iconv.input_encoding
・iconv.output_encoding
・iconv.internal_encoding
・mbstring.http_input
・mbstring.http_output
・mbstring.internal_encoding
</pre>

> iconv (非推奨) や mbstring でのエンコードが設定されている場合は、default_charsetよりもそちらのほうが優先されます。

どうせならdefault_charsetを優先しちゃえばよかったんじゃ。

## 変更された関数

流し読み。

### PHP コア

<pre>
・crypt() で、salt パラメータを省略したときに E_NOTICE が発生するようになりました。
・substr_compare() が、 length パラメータに 0 を受け付けるようになりました。
・unserialize() に渡したシリアライズ済みデータが、
　自身のコンストラクタを呼ばないようなオブジェクトに改変されている場合に、処理が失敗するようになりました。
</pre>

### cURL

<pre>
・@file 構文を使ったアップロードは、 CURLOPT_SAFE_UPLOAD オプションを FALSE にしたときだけサポートするようになりました。
　かわりに CURLFile を使うようにしましょう。
</pre>

### Mcrypt

<pre>
・mcrypt_create_iv() の source パラメータのデフォルトが、 MCRYPT_DEV_RANDOM から MCRYPT_DEV_URANDOM に変わりました。
</pre>

### OpenSSL

<pre>
・stream_socket_enable_crypto() で、 crypto_type パラメータをオプションにすることができるようになりました。
　ストリームの SSL コンテキストに、新しいオプション crypto_type を指定します。
</pre>

### PostgreSQL

<pre>
・pg_insert()、pg_select()、 pg_update()、pg_delete() が、実験的な関数ではなくなりました。
・pg_send_execute()、 pg_send_prepare()、pg_send_query()、 pg_send_query_params() が、
　データベース接続に使っているソケットストリームがノンブロッキングモードの場合は、
　クエリの書き込み完了まで待つようなブロックをしなくなりました。
</pre>

### Reflection

<pre>
・ReflectionClass::newInstanceWithoutConstructor() で、final ではない内部関数をインスタンス化できるようになりました。
</pre>

### XMLReader

<pre>
・XMLReader::getAttributeNs() と XMLReader::getAttributeNo() が、 属性が見つからない場合に NULL を返すようになりました。
　これは XMLReader::getAttribute() と同じ挙動です。
</pre>

## 新しい関数

多いからとりあえずコピペだけ。

### GMP

* gmp_root()
* gmp_rootrem()

### Hash

* hash_equals()

### LDAP

* ldap_escape()
* ldap_modify_batch()

### MySQLi

* mysqli_get_links_stats()

### OCI8

* oci_get_implicit_resultset()

### OpenSSL

* openssl_get_cert_locations()
* openssl_x509_fingerprint()
* openssl_spki_new()
* openssl_spki_verify()
* openssl_spki_export_challenge()
* openssl_spki_export()

### PostgreSQL

* pg_connect_poll()
* pg_consume_input()
* pg_flush()
* pg_socket()

### PDO_PGSQL

* PDO::pgsqlGetNotify()
* PDO::pgsqlGetPid()

### SPL

* SPLFileObject::fread()

### Zip

* ZipArchive::setPassword()

## PHP 5.6.x における OpenSSL 関連の変更

OpenSSL関連は詳しくないので[ここ見てください](http://php.net/manual/ja/migration56.openssl.php)。

## その他の拡張モジュールに対する変更

### OCI8

<pre>
・Oracle Database 12cの暗黙の結果セットをサポートするようになりました。
　新しい関数 oci_get_implicit_resultset() を利用します。
・SELECT に対して ci_execute($s, OCI_NO_AUTO_COMMIT) を使った場合に、
　接続を閉じるときに不要な内部ROLLBACKを起動することがなくなりました。
・DTraceプローブが追加されました。--enable-dtraceオプションで制御します。
・oci_internal_debug()は、何もしない関数になりました。
・phpinfo()におけるOCI8の出力フォーマットが変わりました。
</pre>

Oracle使わないから、調べるのは後回しにする。

### Zip

<pre>
設定オプション --with-libzip が追加されました。
これを指定すると、システムにインストールされている libzip を利用します。
libzip バージョン 0.11 が必須です。0.11.2 以降を推奨します。
</pre>

libzip使ったことないからよくわかんね。
パスワード付きzipを解凍したりするのは、PHP標準じゃダメらしい。
[参考にしたサイト](http://codezine.jp/article/detail/7524?p=2)



## 新しいグローバル定数

(5.6入れたら調べる。)

### LDAP

* LDAP_ESCAPE_DN
* LDAP_ESCAPE_FILTER

### OpenSSL

* OPENSSL_DEFAULT_STREAM_CIPHERS
* STREAM_CRYPTO_METHOD_ANY_CLIENT
* STREAM_CRYPTO_METHOD_ANY_SERVER
* STREAM_CRYPTO_METHOD_TLSv1_0_CLIENT
* STREAM_CRYPTO_METHOD_TLSv1_0_SERVER
* STREAM_CRYPTO_METHOD_TLSv1_1_CLIENT
* STREAM_CRYPTO_METHOD_TLSv1_1_SERVER
* STREAM_CRYPTO_METHOD_TLSv1_2_CLIENT
* STREAM_CRYPTO_METHOD_TLSv1_2_SERVER

### PostgreSQL

* PGSQL_CONNECT_ASYNC
* PGSQL_CONNECTION_AUTH_OK
* PGSQL_CONNECTION_AWAITING_RESPONSE
* PGSQL_CONNECTION_MADE
* PGSQL_CONNECTION_SETENV
* PGSQL_CONNECTION_SSL_STARTUP
* PGSQL_CONNECTION_STARTED
* PGSQL_DML_ESCAPE
* PGSQL_POLLING_ACTIVE
* PGSQL_POLLING_FAILED
* PGSQL_POLLING_OK
* PGSQL_POLLING_READING
* PGSQL_POLLING_WRITING