PHPの今とこれから2021
PHP Conference Japan 2021
October 2, 2021 11:00-11:40
廣川 類 (日本PHPユーザ会)
1
Discord PHP Conference Japan 2021 DAY-1-TRACK1 #track1-k-php2021
自己紹介:ひろかわ
◼ PHPのホビーユーザ(1996~)
◼ PHPマニュアルの日本語化
◼ マルチバイト化:mbstringエクステンション
◼ PHPカンファレンス皆勤中!
◼ PHP関連書籍:
➢ PHP徹底攻略
➢ 初めてのPHP(監訳)
2
PHPとは?
◼ PHPは主にWebアプリケーションに使用されるスクリプト言語
◼ 1995年の誕生以来、Webと共に成長、進化
◼ 現場の課題を簡単に解決してくれる便利なツールです
引用: W3Techs.com, 2021/9/26
65.2%
6.1%
2.9%
2.7%
2.6%
20.5%
CMSシェア WordPress
Shopify
Joomla
Wix
Squarespace
Other
3
78.7%
8.2%
5.4%
3.7% 4.0%
PHP
ASP.NET
Ruby
Java
Other
サーバサイド言語のシェア
PHPアンケート 2021
4
Discord : 投票機能で投票をお願い致します。
DAY-1-TRACK1 #track1-k-php2021
PHPの開発体制
Rasmus Lerdorf
Andi Gutmans
Zeev Suraski
Marcus Boerger
開発アカウント:約2,000名(15名)
コア:約150名(5名)
PHP Group:10名
Nikita Popov
Derick Rethans
https://www.php.net/credits.php
7
20年で速度が50倍に!
(ほぼ)同じスクリプトが動く!
PHPの歩み
bench.php
Ryzen 5 2400G
Ubuntu 20.04
PHPの歩み
8
2011 2012 2013 2014 2015 2016 2017 2018 2019 2020 2021
8.0
`20/11/26
8.1
`21/11/25
2022
5.5
5.6
5.4
Traits
マルチバイト
ジェネレータ
キャッシュ
デバッガ
7.0
7.1
7.2
7.3
7.4
高速化
スカラー型宣言
戻り値型宣言
プロパティ型宣言
FFI
JIT
union
Fiber
enum
PHP 5.3-5.4
現代的な機能導入
PHP7
大幅高速化
PHP8
JIT導入
PHPバージョン分布
引用: W3Techs.com, 2021/9/26
8.0
0.8%
7.4
25.6%
7.3
18.3%
7.2
14.2%
7.1
4.7%
7.0
5.0%
5.x
30.3%
other
1.2%
◼ PHP7ユーザ: 68% (昨年: 58%),PHP 8ユーザ:0.8%
◼ PHP 5(EOL)のユーザ: 30% (昨年: 42%),PHP 7.2まで(EOL)のユーザ:56%
◼ WordPressの推奨環境:PHP 7.4, MySQL 5.6, HTTPS
9
* https://wordpress.org/about/requirements/
◼ PHPのライフサイクル:3年(バグ修正:2年、セキュリティ修正のみ:1年)
◼ EOL以降はセキュリティ関連の修正も提供されず、非常に危険です
◼ PHP5、PHP 7.0/7.1/7.2 は EOLとなっています
PHPリリースサイクル
10
2018 2019 2020 2021 2022 2023 2024
5.6
7.0
7.1
7.2
7.3
7.4
8.0
アクティブサポート セキュリティ修正のみ
2021/10/2
EOL 2018/12/31
http://php.net/supported-versions.php
EOL 2018/12/3
EOL 2019/12/1
EOL 2020/11/30
EOL 2021/12/6
EOL 2022/11/28
EOL 2023/11/26
PHPリリース情報
Release 7.3 7.4 8.0 変更
2020/11/26 7.3.25 7.4.13 8.0.0 PHP 8.0.0 Release, PHP 7.2 EOL (2020/11/28)
2021/1/7 7.3.26 7.4.14 8.0.1 CVE-2020-7071
2021/2/4 7.3.27 7.4.15 8.0.2 CVE-2021-21702
2021/3/4 7.4.16 8.0.3 CVE-2021-21704/21705 (SSRF bypass)
2021/4/29 7.3.28 7.4.18 8.0.5 imap_mail_compose() header injection
2021/5/6 7.4.19 8.0.6 PDO_pgsql: PDO::PARAM_INT
2021/6/3 7.4.20 8.0.7 CVE-2021-21704/21705 (SSRF bypass)
2021/7/1 7.3.29 7.4.21 8.0.8 CVE-2021-21704
2021/7/29 7.4.22 8.0.9 CVE-2020-7068
2021/8/26 7.3.30 7.4.23 8.0.10
2021/9/23 7.3.31 7.4.24 8.0.11 CVE-2021-21706 ZipArchive::extractTo on win32
11
◼ 2021年3月 gitサーバー上のソースコード不正書換え事案発生
◼ CVE-* ⇒ 速やかな更新が必要
◼ 2021年3月28日,主要な開発者(Rasmus Lerdorf氏とNikita Popov氏)の名前
でPHPの開発用ソースコードに対してリモートコード実行脆弱性を生じる不正
なコミットが行われました.
◼ この攻撃は,HTTPヘッダにzerodiumという文字列を含む場合に任意のコード
を実行するという危険なものでした.
◼ このコミットは,PHP開発者によりただちに検出・排除され,PHPのリリー
ス版には影響していません.
◼ 対策として.開発用サーバーをより強固なセキュリティ機構を有するGithubに
移行しました.
PHP開発用コード改ざん事案
PHP8 JIT: より速く、快適に
Ryzen 5 2400G, Ubuntu 20.04 13
0
0.05
0.1
0.15
0.2
0.25
0.3
0.35
0.4
0.45
0.5
PHP
7.4
PHP
8.0
PHP
7.4
cache
PHP
8.0
cache
PHP
8.0
JIT
PHP
8.1
JIT
strcat(200000)
sieve(30)
nestedloop(12)
matrix(20)
heapsort(20000)
hash2(500)
hash1(50000)
fibo(30)
ary3(2000)
ary2(50000)
ary(50000)
ackermann(7)
mandel2
mandel
simpleudcall
◼ PHP 8.1: クラスの継承関係がキャッシュされるようになった (Symfony: 8%改善 )
Zend/bench.php
0
0.5
1
1.5
2
2.5
$x = $f ? $f : tmp
$x = $f ? $f : $a
$x = $f ?: tmp
$x = $a ?: null
$x = $str[0]
$x = $hash['v']
$x = $GLOBALS['v']
$x = $_GET
$x = TEST
new Foo()
$x = Foo::TEST
$this->f()
empty($this->x)
isset($this->x)
$this->x--
$this->x++
--$this->x
++$this->x
$this->x += 2
$this->x = 0
$x = $this->x
Foo::f()
self::f()
empty(Foo::$x)
isset(Foo::$x)
Foo::$x = 0
$x = Foo::$x
empty(self::$x)
isset(self::$x)
self::$x = 0
$x = self::$x
int_func()
undef_func()
func()
empty_loop
Zend/microbench.php
PHP 8.1 改善/変更のポイント
• Fiberによる非同期処理
• 列挙型 (enum:イヌム)
• 交差型
• never型
• readonly指定子
• finalクラス定数
• ‘…’による配列展開
• ‘…’によるクロージャ生成
• newによるデフォルト値指定
• array_is_list関数
• 8進数リテラル表記
• 高速ハッシュ関数
• DNS-over-HTTPS (DoH) のサポート
• ファイルアップロード:full_path追加
• ENT_QUOTES/SUBSTITUTE標準化
• リソース→クラス
• メソッド継承時のstatic変数の共有化
• $GLOBALS変数のアクセス制限強化
Fiber導入
16
https://wiki.php.net/rfc/fibers
✓ ファイバー:簡易的な並列処理,グリーンスレッド
✓ イベントループや処理待ちを簡単に記述できる
✓ ReactPHP, AmPHP がRevolt PHP(イベントループ, Fiber抽象化)共同開発を発表
タスク1
タスク2
タスク3
タスク1
Main Fiber
start
suspend
resume
resume
suspend
$fiber = new Fiber(function () {
echo "中断します¥n";
Fiber::suspend();
echo "再開しました¥n";
});
$fiber->start();
echo "再開します¥n";
$fiber->resume();
協調マルチタスク
逐次処理
Main
列挙型(enum)の導入
17
◼ 列挙型(enumeration)を導入:データ範囲に制約を課せるようになる
◼ クラスなので,メソッドも定義可能
RFC: https://wiki.php.net/rfc/enumerations
var_dump(Status::BETA);
var_dump(Status::BETA->value);
enum(Status::BETA)
string(12) "Beta Release"
enum Status : string {
case ALPHA = "Alpha Release";
case BETA = "Beta Release";
case RELEASE = "Public Release";
public function getVersion(): string {
return match($this) {
Status::ALPHA, Status::BETA => '0.x',
Status::RELEASE => '1.0'
};
}
}
var_dump(Status::ALPHA->getVersion());
string(3) "0.x"
交差型(Intersection)の導入
18
class Test {
private Traversable&Countable $ci;
public function setIterator(Traversable&Countable $c) {
$this->ci = c;
}
public function getIterator(): Traversable&Countable {
return $this->ci;
}
}
◼ 合併型(Union): PHP 8.0で導入,引数・戻り値の型の候補を複数指定
◼ 交差型(Intersection): PHP 8.1で導入, 積集合
◼ クラス(インターフェイス)でのみ使用可能
RFC: https://wiki.php.net/rfc/pure-intersection-types
function redirect(string $uri): never {
if ($uri==='') {return;}
header('Location:'.$uri);
exit();
}
never型
19
function redirect(string $uri): never {
header('Location:'.$uri);
exit();
}
◼ 処理を戻さないことを指定 ⇒ 常に throw または exit
◼ 開発時に整合性を確認できる.
RFC: https://wiki.php.net/rfc/noreturn_type
処理を戻すとエラー発生
A never-returning function must not return
値を戻す処理を追加
readonly指定子
20
class Test {
public readonly string $prop;
public function __construct(string $v) {
$this->prop=$v;
}
}
◼ 読み込みのみ可能を指定
◼ 初期化後は書き込み不可となる
◼ 型を指定する変数のみ指定可能(指定しない場合はmixedを指定)
RFC: https://wiki.php.net/rfc/readonly_properties_v2
$obj = new Test("foo");
var_dump($obj->prop); // foo
$obj->prop="boo";
書き込むとエラー発生
初期化時はOK
Cannot modify readonly property Test::$prop
finalクラス定数
21
◼ 従来:クラス定数は子クラスで上書きできてしまう.
◼ PHP 8.1:finalをつけることで変更禁止となる.
RFC: https://wiki.php.net/rfc/final_class_const
class Foo {
public const X = "foo";
}
class Bar extends Foo {
public const X = "bar";
}
class Foo {
final public const X = "foo";
}
class Bar extends Foo {
public const X = "bar";
}
PHP 8.1
PHP Fatal error: Bar::X cannot override final constant Foo::X
‘…’ による配列展開
22
◼ PHP 5.6:
関数引数における展開演算子
(...)
$a=["a"=>1];
$b=["b"=>2];
$c=["a"=>0,...$a,...$b];
var_dump($c); // “a”=>1, “b”=>2
RFC:https://wiki.php.net/rfc/array_unpacking_string_keys
$a=[1,2];
$b=[3];
$c=[0,...$a,...$b];
var_dump($c); // [0,1,2,3]
function test(){ var_dump(func_get_args());}
$a=[1,2];
$b=[3];
test(...$a,...$b); // [1,2,3]
◼ PHP 7.4:
添字配列における展開演算子
(...)
◼ PHP 8.1:
連想配列における展開演算子
(...)
‘...’構文によるクロージャ
23
RFC: https://wiki.php.net/rfc/first_class_callable_syntax
◼ PHP 7.1 : callable をクロージャに変換する仕組み導入
public static Closure::fromCallable(callable $callback) : Closure
◼ PHP 8.1 : ‘…’ 構文で簡易的に同じことができるようになった
$fn = Closure::fromCallable('strlen');
$fn = strlen(...);
PHP 8.1
new式による引数デフォルト値
24
◼ パラメータにデフォルト値としてnewオブジェクトを直接指定できるようになる.
class Test {
private Logger $log;
public function __construct(?Logger $log = null) {
$this->log=$log ?? new NullLogger;
}
}
RFC: https://wiki.php.net/rfc/new_in_initializers
class Test {
public function __construct(private Logger $log = new NullLogger) {}
}
PHP 8.1
array_is_list関数
25
◼ 添字配列(リスト)と連想配列を判別
RFC: https://wiki.php.net/rfc/is_list
var_dump(array_is_list([0,1,2]));
var_dump(array_is_list(['1'=>1,'2'=>2]));
var_dump(array_is_list(['0'=>0,'1'=>1,'2'=>2]));
bool(true)
bool(false)
bool(true)
明示的な8進数リテラル表記
26
◼ 従来の8進数リテラル表記 0dd… は,紛らわしかった.
◼ 新たな8進数リテラル表記:0odd… を導入 (16進数表記 (0xdd) に類似)
RFC: https://wiki.php.net/rfc/explicit_octal_notation
var_dump(016===16);
var_dump(016===14);
PHP 8.1
var_dump(0o16===14);
bool(false)
bool(true)
bool(true)
0
2
4
6
8
10
12
14
高速ハッシュアルゴリズム追加
◼ 高速ハッシュアルゴリズム MurmurHash3, xxHash 導入 (非暗号学的ハッシュ)
処理速度(sha256に対する比, 10MB)
$hash=hash('murmur3f', $content);
Ryzen 5 2400G
Ubuntu 20.04
DNS-over-HTTPS (DoH)のサポート
28
◼ CurlエクステンションにおけるDNS-over-HTTPS (DoH)のサポート
$ch = curl_init('https://www.yahoo.co.jp');
curl_setopt($ch, CURLOPT_DOH_URL, 'https://dns.google/dns-query');
curl_exec($ch);
HTML関連関数:ENT_QUOTES/SUBSTITUTE標準化
29
◼ htmlentities(),htmlspecialchars(): ENT_QUOTES/ENT_SUBSTITUTE標準化
◼ 不正文字:従来は削除,PHP 8.1では�で代替
$str = "java¥xffscript:alert('XSS’)”;
echo htmlentities($str);
'quote' is <b>bold</b>
'quote' is <b>bold</b>
java�script:alert('XSS')
PHP 8.1
PHP 8.1
$str = "'quote' is <b>bold</b>";
echo htmlentities($str);
メソッド継承におけるstatic変数
30
◼ クラスメソッド継承におけるstatic変数の扱い変更:独立→共有
class A { // static var in method
public static function counter() {
static $cnt = 0;
return ++$cnt;
}
}
class B extends A {}
var_dump(A::counter());
var_dump(A::counter());
var_dump(B::counter());
var_dump(B::counter());
int(1)
int(2)
int(3)
int(4)
PHP 8.1
class A { // static var in class
private static $cnt = 0;
public static function counter() {
return ++static::$cnt;
}
}
class B extends A {}
int(1)
int(2)
int(3)
int(4)
int(1)
int(2)
int(1)
Int(2)
従来
https://wiki.php.net/rfc/static_variable_inheritance
リソースからクラスへの移行
31
◼ 長期的目標: 全てのリソースオブジェクトをクラスオブジェクトに移行する
◼ 戻り値は変わるが,後方互換性維持のため,パラメータ等は変更なし
◼ 標準組込み関数にも名前空間を導入 password_hash() → Password¥hash()
https://wiki.php.net/rfc/namespaces_in_bundled_extensions
https://github.com/php/php-tasks/issues/6
PHP 8.0
PHP 8.1
cURL, enchant, GD, OpenSSL, shmop, sockets, sysvmsg/sysvsem/sysvshm,
XML, XML-RPC, XMLWriter, zip, zlib
finfo, ftp, GD, pspell, imap, LDAP
残り
Com, dba, MySQLi, OCI8, ODBC, PDO, pgsql, proc, SOAP, stream
PHP の将来
◼ PHPスクリプトの用途拡大:Opcache(プリローディング)+JIT+FFIの活用
1.PHPエクステンション:C言語による記述からPHPによる記述へ(FFI)
2.計算負荷が高いアルゴリズムのPHPによる実装:機械学習・AI等 (PHP-ML, Rubix ML)
32
入力処理(C言語)
外部API実行
PHPスクリプト
従来のエクステンション(C言語)
出力処理(C言語)
PHP出力
入力処理(PHP)
外部API実行
PHPスクリプト
FFIエクステンション(PHP)
出力処理(PHP)
PHP出力
https://rubixml.com/
Rubix ML
PHPユーザ相互の情報交換
およびコミュニティの健全な発展
設立趣旨 活動内容
ドキュメント整備
セミナー/イベント
メンバー/スタッフ
国際化
Web/SNS
• PHPユーザ会員と思ったらメンバー
• 運営してみるのも楽しいかも
日本PHPユーザ会
(2000年4月発足)
PHPカンファレンス
33
PHP勉強会
34
◼ 2021年のPHPカンファレンスは,新型コロナウイルス(COVID-19)感染症拡大
防止のため、昨年に続きオンライン開催となります。
◼ 今年は,なんと二日間!思う存分お楽しみください!
◼ オンライン開催では「YouTube Live」を利用したライブでのセッションを始め、
オンラインならではのコンテンツで今年のカンファレンスをお楽しみください。

PHPの今とこれから2021