PHPの最新状況:PHP 7.4の開発状況(第9回 著:廣川類氏)

  • 2019.11.11
  • PHP
PHPの最新状況:PHP 7.4の開発状況(第9回 著:廣川類氏)
Bookmark this on Hatena Bookmark

秋の終わりから冬にかけてすっかり寒くなり、今年一年も残り少なくなっています。いよいよPHP 7.4の開発も11月末のリリースに向けて大詰めを迎えています。今回のコラムでは、前回に続き、PHP 7.4における変更点について解説します。

PHP 7.4の開発状況

 PHPの最新版であるバージョン7の最新版はPHP 7.3ですが、次のマイナーバージョンアップ版にあたるPHP 7.4の開発が順調に進んでいます。これまでに、ほぼ最終リリース版に相当するリリース候補が9月以降5回リリースされ、最終段階のテストが行われています。今後、最後のリリース候補版RC6が11月14日にリリースされた後、大きな問題が発生しない限り計画通り11月28日の正式公開が行われる予定です。

これまでに、PHP 7.4の以下に示す主な新機能について紹介してきました。

  1. OpCacheのプリロード機能
  2. クラスプロパティの型指定追加
  3. FFI (Foreign Function Interface)機能
  4. 配列スプレッド構文
  5. アロー関数
  6. ??= 構文

今回は、いままで紹介していない以下の新機能および廃止される機能について紹介します。

  1. mb_str_split()関数追加
  2. 数値リテラルセパレータ導入
  3. 弱い参照の導入
  4. 演算子(+ .)の優先順位変更
  5. 共変戻り値と反変パラメータに対応
  6. 廃止対象となる機能

1から3が機能の追加、4および5は従来機能があいまいであったり一貫性がなかった部分の変更となります。以下、順番に紹介していきます。

mb_str_split()関数追加

日本語を含むマルチバイト処理を行うエクステンションであるmbstringエクステンションに関数が追加されます。マルチバイト文字を指定した長さで配列に分割するもので、従来サポートされているstr_split()関数のマルチバイト文字対応版となります。文字列を2文字毎に分割する簡単な使用例をリスト1に示します。

リスト1 mb_str_split関数の使用例

———————————————————-

$a = mb_str_split(“日本語と英語”, 2));

// 配列 $a[0]=>”日本”, $a[1]=>”語と”, $a[2]=>”英語”

———————————————————-

数値リテラルセパレータ

桁数が多い数値を記載する際に便利な機能としてセパレータがサポートされました。例えば、$foo=1000000 は、$foo=1_000_000 のように記載できるようになります。桁の多い数値もセパレータを入れると見やすくなり、間違いを減らすことが期待できます。

弱い参照

 PHP 7.4では、弱い参照(Weak Reference)が導入されます。従来の参照(リファレンス)との差異は、弱い参照ではオブジェクトの破棄に影響を及ぼさないことです。キャッシュのような構造を実装する際に記述を簡単になることが期待されます。

弱い参照を作成する際には、WeakReferenceクラスのcreateメソッドをスタティックコールします。クラスオブジェクト$objの弱い参照を作成するには、以下のようなコードを実行します。

$ref = WeakReference::create($obj);

 弱い参照によるオブジェクトの実際の参照はgetメソッドにより、$ref->get()のように行われます。まず、リスト2に従来の参照の例を示します。

リスト2 従来の参照の例

———————————————————-

$obj=new stdClass;

debug_zval_dump($obj); // object(stdclass)#1 refcount(2)

$ref = $obj; // シャローコピー

debug_zval_dump($obj); // object(stdclass)#1 refcount(3)

debug_zval_dump($ref); // object(stdclass)#1 refcount(3)

unset($obj); // コピー元削除

debug_zval_dump($ref); // object(stdclass)#1 refcount(2)

———————————————————-

3行目で$refにオブジェクト変数$objをコピーしています。PHPでは、デフォルトでシャローコピーが行われ、実体が別に作成されることなく、参照が作成されます。ある変数が別の変数にコピーされ、その変数の実体が参照される数が増えるとリファレンスカウンタの数が増加します。

代入の前後(2行目と4行目の間)に実行されたdebug_zval_dump()関数の出力において、リファレンスカウンタが増加しているのはこのためです。4行目と5行目で参照されるオブジェクトの実体が同じ#1であることも確認できます。次に6行目で元のオブジェクト変数$objを削除すると、実体を参照する変数が減るため、7行目でリファレンスカウンタの数が1つ減っていることが確認できます。

次にPHP 7.4で導入される弱い参照の例をリスト3に示します。

リスト3 弱い参照の例

———————————————————-

$obj=new stdClass;

debug_zval_dump($obj); // object(stdclass)#1 refcount(2)

$ref = WeakReference::create($obj);

debug_zval_dump($obj); // object(stdclass)#1 refcount(2)

debug_zval_dump($ref->get()); // object(stdclass)#1 refcount(2)

unset($obj); // コピー元削除

debug_zval_dump($ref->get()); // NULL

———————————————————-

3行目でオブジェクト変数を$refに代入しますが、今回は弱い参照による代入を用います。リスト2と異なり、代入の前後(2行目と4行目の間)でリファレンスカウンタは変化していません。6行目で元のオブジェクト変数$objを削除した後、7行目で弱い参照のオブジェクトを$ref->get()メソッドで参照するとNULLが返されます。リスト2では、コピーの際にリファレンスカウンタが増えていたため、元の変数が削除されて、リファレンスカウンタが減った場合でも変数の実体が削除されなかったのですが、弱い参照の場合は、リファレンスカウンタに影響を与えないので、元の変数の実体は参照されているかによらず削除されたということになります。この動作は、従来の参照とは異なるため注意が必要になりますが、キャッシュの整理など、実体を確実に消去してリソースを開放したい場合には、実装を容易にすることができると期待されます。

 演算子(+ .)の優先順位変更

従来のバージョンでは、‘.’、’+’、’-‘演算子は等しく扱われており、左から右に評価されてきました。しかし、これらの演算子が同時に使用された場合、意図せずに数値が文字列に変換されることで、プログラマの意図とは異なる動作となるケースがありました。例えば、変数$aと$bが数値である場合、以下のコードで$aと$bの合計を表示しようとした場合を考えてみましょう。

echo “sum: “ . $a+$b;

実際には、優先順位が同じ演算子が並ぶため、以下のように左から右に演算子が評価されます。これにより、$aが文字列に変換されて結合され、$bも文字列として結合されてしまいます。

echo (“sum:” . $a) + $b;

この例では、以下のように括弧で括ることで優先順位をあげる必要があります。

echo “sum: “ . ($a+$b);

上記のコードは、結論からすると、プログラマのコードが間違っていたバグの類なのですが、多くのプログラマの直感的な動作と異なっていることは間違いを生みやすい仕様といえます。

PHP 7.4では、’+’または’-‘の前にある’’.’の分離し、加算または減算が先行して行われるようになります。

 例えば、以下のコードの出力は、PHP 7.3までは35でした。

echo “3” . “5” + 7 

 これは、まず左から右に文字列として結合され、”35”+7となった後、加算の評価を行う際に”35”が数値として評価されて、42となったためです。

 同じコードをPHP 7.4で実行すると、”312”となります。これは、まず、”5”+7が実行されて12となった後、文字列として”3”に結合されるためです。この仕様変更は、プログラマの直感に近いものとなりますので、間違いを減らしてくれるものと期待されます。ただし、既存のコードに影響を与えることが懸念されます。これを確かめるため、PHPのコア開発者であるNikita Popov氏は、上位2000個のComposerパッケージを調査し、この仕様変更の影響を調査しました。これによると、5件ほどが影響を受けることが判明したとのことですが、実際にはこの5件はすべてバグであることが確認され、逆に今回の仕様変更の効果が確認されたとのことです。

 共変戻り値と反変パラメータに対応

従来、リスト4のようなコードを実行すると、6行目で以下のような警告が発生していました。

Warning: Declaration of D::foo(A $foo):D should be compatible with C::foo(A $foo):C

リスト4 警告を発生する戻り値指定の例

———————————————————-

class A {}

class C {

  public function foo(A $foo) : C {}

}

class D extends C {

  public function foo(A $foo) : D {}

}

———————————————————-

 本来、クラスDはクラスCを継承しているため、fooメソッドの戻り値としてDを指定しても矛盾はないはずなのですが、従来のPHPでは依存関係を正しく判別できず、警告を発生していました。PHP 7.4以降では、この依存関係が正しく判別され、このようなケースでの警告は発生しなくなります。

 同様に、従来のPHPにおいては、リスト5のようなケースでも7行目で警告を発生していました。

リスト5 警告を発生するパラメータ指定の例

———————————————————-

class A {}

class B extends A {}

class C {

  public function foo(B $foo)  {}

}

class D extends C {

  public function foo(A $foo)  {}

}

———————————————————-

 クラスBはクラスAを継承しているため、型指定として矛盾はないはずですが、従来のPHPでは依存関係を正しく扱うことができなかったため、警告を発生していました。PHP 7.4では、このようなケースでも警告を発生しないようになります。

 廃止対象となる機能

 以下に示す機能は、PHP 7.4で廃止対象となり、deprecate警告を発生するようになります。これらの機能では、PHP 8で正式に廃止される予定です。

  1. real型
  2. 波括弧による配列オフセット指定
  3. magic quotes関連の関数
  4. allow_url_includeパラメータ

現在、float型にはdoubleとrealの2種類のエイリアスが定義されていますが、後者はほとんど使用されていないため、廃止対象となりました。(real)変数名のような型キャストとis_real()関数の両方が廃止となります。それぞれ、(float)変数名、is_float()関数に置き換えることで対処できます。

 magic_quotes機能は、入力変数に対するセキュリティ対策として使用された時期もありましたが、抜け穴がありセキュリティホールを生み出しやすかったため、magic_quotesオプションはPHP 5.4で廃止となっています。しかし、関連する関数であるget_magic_quotes_gpc() およびget_magic_quotes_runtime()については、下位互換性維持のため、常にFALSEを返す関数として定義が残っていました。今回、これらの関数は廃止対象となります。

また、フィルタ機能でFILTER_SANITIZE_MAGIC_QUOTES定数を指定した場合、PHP 5.4以降、magic quotesが廃止されたため、addslashes()関数が代わりに適用されてきました。PHP 7.3で新たにFILTER_SANITIZE_ADD_SLASHES定数が定義され、同様の動作がより直接的に表現されるようになりました。このため、FILTER_SANITIZE_MAGIC_QUOTES定数は廃止対象となります。

allow_url_includeパラメータは、require、require_once、include、include_onceでURLストリームを利用できるようにするものですが、外部データを取り込むことでセキュリティ上の問題を発生しやすいため、廃止対象となりました。

Bookmark this on Hatena Bookmark

PHPカテゴリの最新記事