半端なPHPDisでPHPerに陰で笑われないための 
Perl Monger向け最新PHP事情 
   
YAPC::Asia 2014 
@uzulla
Breaking news 
(このタイミングでリリース…)
Meanwhile in 
YAPC::Europe 2014
I am ... 
@uzulla 
Hachioji.pm 
PHPer
I ❤️ 
PHP
皆さんに質問 
PHPを使っている人?
PHPに苦しめられ 
ている人? 
DISりたくてここに 
いる人?
Do you know 
PHP ?
PHP is ... ? 
• Webに特化 
• LAMPというありふれた環境 
(Linux Apache Mysql PHP) 
• 初心者でもイケるゆるふわなコード 
• 「Wordpress」「ECCUBE」 
「phpMyAdmin」等といった超有名アプリ
PHP is .... ? 
• レンタルサーバー(レン鯖) 
• FTPでデプロイ 
• 関数のかたまり 
• レガシーコードがやばい 
• テンプレートエンジン(笑)
Q: PHPはテンプレートエンジ 
ン? 
A: はい 
PHP: Hypertext Preprocessor
... 
<div id="user_name"> 
<?php echo $_GET['name']; ?> 
</div> 
...
Q: DBつかえるってきいたけ 
ど? 
A: 勿論です 
Mysql,sqlite,Pgsql,Oracle,Sqlserver ...
traditional PHP code 
<div id="user_name"> 
<?php 
$db = mysql_connect('localhost', 'yay_id', 'yay_pass'); 
mysql_select_db('yay', $db); 
$res = mysql_query("SELECT * FROM user_account 
WHERE user_id=".$_GET['id']); 
$row = mysql_fetch_assoc($res); 
echo $row['name']; 
?> 
</div>
transitional PHP code 
<div id="user_name"> 
<?php 
if(isset($_GET['id'])&&is_string($_GET['id'])){ 
$id = (int)$_GET['id']; 
try { 
$pdo = new PDO('mysql:host=localhost;dbname=yay;charset=utf8mb4', 'yay_id', 'yay_pass'); 
$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); 
$stmt = $pdo->prepare('SELECT * FROM user_account WHERE user_id=:user_id'); 
$stmt->bindValue('user_id', $id, PDO::PARAM_INT); 
$sth = $stmt->execute(); 
$user = $sth->fetch(PDO::FETCH_ASSOC); 
if(!empty($user)){ 
echo htmlspecialchars($user[0]['name'], ENT_QUOTES, "UTF-8"); 
}else{ 
echo "oh, i don't know that id."; 
} 
$pdo = null; 
} catch (PDOException $e) { 
if(count(ob_get_status())===0){ http_response_code(500); } 
error_log("db fail ".$e->getMessage()); 
echo "oh, db fail sorry."; 
} catch (Exception $e) { 
if(count(ob_get_status())===0){ http_response_code(500); } 
error_log("terrible error".$e->getMessage()); 
echo "uhoh, sorry."; 
} finally { 
// it's joke. 
} 
}else{ 
echo "oh, id is require."; 
} 
?> 
</div>
…もう帰りたい? 
(NAOYAさんの発表が裏ですよ!)
MODERN PHP ?
MODERN PHP (probably) 
• オブジェクト指向プログラミングを駆使 
• イケてるライブラリを使う 
• 「Herokuにデプロイ」 
• 「継続的テストも必須だよね」 
• とかなんやかんや、やる感じ 
個人差有ります
Q: まって、テンプレートエン 
ジンじゃないの?
Q: まって、テンプレートエン 
ジンじゃないの? 
A: PHPはクラス、インターフェイス、抽象クラ 
スと基本からはじまり、単一継承ではあるものの 
Traitによって柔軟さを確保し、例外機構、 
Finalizeなどもきちんと存在し、簡単なメタプロ 
もできる程度のマジックメソッドを持ったオブジ 
ェクト指向プログラミング対応のテンプレートエ 
ンジンです。
A『は?飛躍したぞ?』 
B「OOPって =& のこと?」 
C『PEARのことでしょ?』
論よりナントカ 
百聞は一見にしかず 
とりあえずウェブアプリケーションを作ってみま 
す。残念ながらライブではありません。
はじめる前に 
• Windows > PHPはいってない 
(XAMPPとかWebmatrixとかで入る) 
• Linux > (Cent5以外なら)AptとかYumとか 
• Mac > 「それマヴェリック?もう5.4はいって 
るよ!!」 
Macの人はすぐにできます
そんなに慌てて 
PHPを削除しない 
でください
1,ディレクトリ作ります
2,Composerをいれます。 
ワンライナーで入る。 
ComposerはPerlで言う所のcpanmみたいなパッ 
ケージマネージャです。
3,おもむろにWAFをインストールします。 
※今後php composer.pharをcomposerとタイプ 
します
4,コードを書く 
$ (vim|emacs) index.php
5,PHPでサーバーをたてる 
• plackupみたいなの(開発のみに使う) 
• PHP>=5.4からhttpdが組み込み 
• コンソールに色つきログが出て便利 
• (余談:HTML開発にもつかえる)
6,hello world! 
Tadaa!!!できた!!! 
(Composerを手元で走らせて全部あげれば、世 
の中の90%(適当)の実行環境であるレンサバでも 
問題ありません)
繰り返しになりますが 
Macをお使いの皆さんは 
• 宗教上の理由 
• お医者さんに止められている 
• 家族の薦め、死んだ婆さんの遺言 
とかないかぎり今すぐ使えますよ! 
言い訳はできません
PHPのOOPの話
…の前に、クラスのロード方法 
• 古代:全部コピペ(そもそも非クラス) 
• 昔 :先頭に大量のrequire_once() 
• 近代:自前でオートローダーを実装 
• 現代:PSR-0,4対応のローダー 
(主にComposerの機能) 
(番外 PEARはinclude_path)
Composerのオートローダーの設定 
composer.json修正→composer update(等)
Composerのオートローダーの利用 
<?php 
require_once('vendor/autoload.php'); 
vendor/autoload.phpをrequire_onceするだけ
クラス名、ファイル名規約、 
PSR-0(または4) 
• 昔は規約なんてなかった、カオスだった 
• Net_Services_Twitterとか…(長い) 
• 今はネームスペースを使う 
• ネームスペース例 
UzullaMyLibrary 
• それに対応するファイルパス例 
/path/to/lib/Uzulla/My/Library.php
「PSR」? 
• PHPの規約、PHP-FIGが策定(PHP本体ではな 
い) 
http://www.php-fig.org/ 
• 策定済→ 0,4:Auto load周り 
1,2:code style系、3:Logger Interface 
• 策定中→ 5:PHPDoc、6:Cache Interface 
• 世紀末フリーダム世界PHPに秩序を
さっさとOOP 
はい
こういう感じのファイル配置 
(PSR-4だとYapcはショートカットできるけどわか 
りやすさの為)
コントローラーのベースクラスがこんなんで 
Yapc/Controller/Base.php 
<?php 
namespace YapcController; 
use SlimSlim; 
class Base 
{ 
protected $slim; 
public function __construct(){ 
$this->slim = Slim::getInstance(); 
} 
}
継承したクラスはこんなんです 
Yapc/Controller/Index.php 
<?php 
namespace YapcController; 
class Index extends Base 
{ 
public function run(){ 
$this->slim->render('template/index.twig'); 
} 
}
Perlだと?(雰囲気です) 
package Index; 
use Mouse; 
extends 'Base'; 
has slim => ( is => 'rw', isa => 'Slim' ); 
sub run { 
my ($self) = @_; 
$self->slim->render('template/index.tt'); 
} 
no Mouse; 
1;
PHPのOOP…これは… 
• JavaっぽいのOOP、Blessみたいなのはない 
• 「OOPの本」とかの例が(ある程度)書ける
つまり怖くない 
気付いてる人は気付いてると思いますが、 
PHPはHTMLのテンプレートエンジンですが、 
PHPのコード内にはHTMLは一切かかず、 
普通のプログラミング言語のフリをして使うのが 
今の書き方です。
Q: じゃあHTMLはどこに書くの? 
A: テンプレートエンジンである所のPHPで書か 
れた、別な安全なテンプレートエンジンを使うと 
良いでしょう!! 
冗談ではありません。 
PHPはHTMLの中でいきなりDBにSELECTとかで 
きて強力すぎるし、オートエスケープがないの 
で、正しく安全に使うのは非常に面倒。 
なので、Twigとかつかうべきでしょう。
Type Hinting 
function ( MyClass $my_class_instance ){ 
• 引数の「型」っぽくクラス名書ける 
• クラス名、インターフェイス名、array等 
• 間違えると例外が上がって安心 
• 静的解析がはかどる 
=>IDEが補完ガンガン(超重要)
でも…残念… 
• integer、Stringなどのスカラ型がない 
• traitもダメ 
※PHP.netでRFCにはなってるのでいつかは… 
(でも「…そうか…」という箇所もある) 
https://wiki.php.net/rfc/ 
scalar_type_hinting_with_cast
独自例外クラス 
<?php 
namespace Yapc; 
class MyException extends Exception 
{ 
public function scream(){ 
echo "うぎゃ~"; 
} 
}
独自例外クラスをキャッチとFinally 
<?php 
try { 
if($hoge){ throw new Exception('汎用'); } 
if($huge){ throw new YapcMyException('オレオレ'); } 
} catch (YapcMyException $e) { //独自例外クラス 
$e->scream(); // <--独自例外に生やしたやつ 
} catch (Exception $e) { //そのほか 
echo $e->getMessage(); 
} finally { // PHP>=5.5から使える 
echo "終わりだ…"; 
}
SPL 
• Standard PHP Library 
• 色々な継承に使えるテンプレートがある 
• イテレータとかイテレータとか 
• 継承でForeachにわたせるようになるとか 
• 例外とか例外とか例外とか 
• 独自例外つくるより選ぶ方が楽
他にも… 
• __set(),__get()、__toString()、 
__clone()等の少々のマジックメソッド 
• final指定 
• trait 
(多重継承の代用等)
OOPじゃないけど 
• password_hash (PHP>=5.5) 
「PHPerでも」「将来にわたって使いやすい」 
「安全な」パスワードハッシュをつくれる 
• Generator (PHP>=5.5) 
巨大ファイルや終わりの不明なデータ処理につ 
かいやすい。 
• [1,2] (配列リテラル)(PHP>=5.4) 
昔はarray(1,2)というダサイ記法だった
OOPじゃないけど2 
IDEによるリアルタイムLint 
Typoや未宣言変数の指摘 
クラス名の重複や
未使用変数の指摘 
「型」の違う変数の指摘 
めっちゃイライラが減る!!! 
「自分よりPHPStorm(等)が信用できる」
まとめ 
• PHPはOOPできるようにがんばってる 
• 例外とかもちゃんとある 
• 「Javaっぽい?」 
• IDEの静的解析が果てしなく便利 
=> プロはIDEいらないかもですが 
=> 補完のために自然とクラスを作り出す
PHP5.6 
-RC4 now- 
Released!! Yeah!!
• (割とマニアックな機能追加が多い) 
• 累乗演算子、GMPの演算子オーバーロード 
• (constによる)定数宣言で式利用可能に 
• 可変長引数記法や関数の名前空間、誰得? 
• 各種制限撤廃は嬉しい 
(php://input再利用可、 
ファイルアップロード2GBの天井消滅) 
• 「余波で」PHP5.3が終了へ(これは重要)
ライブラリ
最近のライブラリ事情 
• PEARは消滅の流れ(PHPUnit、AWSなど) 
• Packagist+Composerが台頭 
• Packagist.orgのRSSが加速している 
=> PHPのライブラリがドンドンふえている! 
(=>「ACME」ライブラリも多い…)
Packagist ? 
• http://packagist.org 
• ライブラリのリポジトリ(インデクスのみ) 
• npm,rubygemsと似てる 
• Composerから利用される 
• ホストはGithub 95%(適当体感)、残り 
Bitbucketなど 
• 登録・投稿に一切の審査無し
増え続けるパッケージ(2014/08/25) 
• 「36772 packages registered」 
• 「142437 versions available」
http://www.modulecounts.com/
Packagist監視業務は結構たのしい(つらい) 
• よくわからんWAF 
• よくわからんORM 
• よくわからんルーター 
• よくわからんテンプレートエンジン 
• 「砂場では?」「スターを見よう…」 
• 監視業にはRSSが便利 
• Twitter: @call_user_func
監視おじさんのスターリストから 
• id:uzullaのGithubのスターリストから抜粋 
• ライブラリやツール 
• 全部試した訳ではない 
• 趣味、偏りがあります
• https://github.com/Seldaek/monolog 
鉄板なLogger 
• https://github.com/fabpot/Twig 
鉄板なテンプレートエンジン 
• https://github.com/sebastianbergmann/ 
phpunit 
鉄板のテストフレームワーク 
• https://github.com/fabpot/Goutte 
要はLWP 
• https://github.com/swiftmailer/swiftmailer 
鉄板のメール送信するやつ
• https://github.com/Halleck45/PhpMetrics 
コードを静的解析してスコアつけとかするやつ 
• https://github.com/squizlabs/PHPCodeSniffer 
要はPerl::Critic、Perl::Lint 
(他にもPHPMD) 
• https://github.com/fabpot/PHP-CS-Fixer 
コードフォーマット修正ツール 
(PHPStormがあるからつかってない…) 
• https://github.com/bobthecow/psysh 
組み込みより高機能なREPL
• https://github.com/Bee-Lab/bowerphp 
JavascriptのBowerコンパチツール 
• https://github.com/indeyets/pake 
要はmake的なやつ 
• https://github.com/rocketeers/rocketeer 
デプロイツール 
• https://github.com/nategood/commando 
PHPでCLIプログラム書く時につかうGetOp的 
ライブラリ
• https://github.com/illuminate/database 
LaravelというWAFのORM部分切り出し 
• https://github.com/j4mie/idiorm 
要はORM 
• https://github.com/jpfuentes2/php-activerecord 
要はActiveRecord(他にもARはある) 
• https://github.com/memememomo/php-SQL-Maker 
要はSQL::Maker
• https://github.com/clue/psocksd 
SOCKSトンネル、サーバーデーモンの実装の 
やつ 
• https://github.com/bravo3/ssh 
sshクライアント的なやつ 
• https://github.com/fpoirotte/pssht 
ssh「サーバー」 
• https://github.com/clue/php-wake-on-lan-react 
WOL(WakeOnLan)叩くやつ
• https://github.com/reactphp/react 
「Event-driven, non-blocking I/O with PHP.」 
• https://github.com/ratchetphp/Ratchet 
WebSocketサーバー(スタンドアロンでサーバ 
ーになります) 
• https://github.com/marcj/php-pm 
「PHP ProcessManager for Request-Response 
Applications」
• https://github.com/videlalvaro/phacterl 
「Implementation of The Actor Model in 
PHP.」 
「アクターモデル」「マジで!?」 
• https://github.com/ircmaxell/PHPPHP 
「A PHP VM implementation written in PHP.」 
「PHPでPHP実装した」「マジで?!」 
• https://github.com/runekaagaard/snowscript 
要はPHPのCoffeScript、更新ほぼない
ライブラリまとめ 
• かなり面白いライブラリやツール増えた 
• 「これPHPでやるドメインか??」 
• 「ホントに動くのかこれ??」 
• Packagistは自分でも気軽に登録できる 
• 国産ライブラリもっと増えて欲しい
実行環境
「PHPの実行環境は沢山あるんじゃ 
ぞ」 
本家PHP、HHVM、HippyVM、PHP.js、Quercus、 
Phalanger、pipp、HappyJIT、PHP Compiler 
(PHC)、Rose、Roadsend PHP、Roadsend PHP: 
Raven (RPHP)Project_Zero/sMash、talaria 
Runtime、PHP4Mono、php-llvm、Zend Server
「本当の所は?」 
実用できるのは以下三つ 
• 本家PHP 
• HHVM 
• ZendServer 
ZendServerは有料なのでよくわからないけど、プ 
ロファイラとか、5.3を今後もサポートとか、そ 
ういう強みがある模様
本家の特徴 
• 本物である 
• pecl(c拡張)がつかえる 
• 安定している 
• mod_phpがある
HHVMの特徴 
• 速い 
• 速い 
• なんかカッコイイ 
• httpd 動作可能 
• チョイチョイたりない互換性 
• Hack langつかえる 
• 速い
Q: どっちをつかうべきでしょうか? 
A: 本家です
本家?HHVM? 
• どっちか迷う人がHHVMはやめた方が良い 
• 速度以外のメリットはない(大体倍) 
• でも、実際のネックはDBとかでしょ? 
• 「本家でありえない物」も、あまりない 
(将来永続インスタンスとかでてきたらワンチ 
ャンあるで) 
• Hack?使ってる所をまだみたことない
「ところでLAMPはオワコン?」 
「nginx+PHPが今ドキでは?」
Apacheの特徴 
• htaccessの楽さ 
• mod_phpとmod_rewriteの組み合わせは 
やっぱり柔軟で強力 
(FastCGIはURIのマップでかゆいところに手 
が届かないか、コンフィグが複雑で面倒) 
• 手間&手離れ
nginxの特徴 
• 特に遅いモバイル相手で裁ける量が違う 
• 複数アプリを相乗りしだすと色々面倒 
(複数のrepoがデプロイされてるとか…) 
• 協力会社とお客様のご理解 
(「なんでhtaccessがないの!?」 
 「(秘伝のタレ)を置いて下さい」) 
• 監視点や監視ログが増える
まとめ 
• 「PHPらしく」つかうとLAMPしかない事も 
• Apache+mod_phpの楽さ、柔軟さハンパない 
• nginx+php-fpmは速度が欲しければ良い 
• nginx+HHVM(fastCGI)は最悪php-fpmに戻せる
それPHP?
PHPの欠点 
遅い
本当なの? 
• plackで 1000req/s の所 50~300req/sくらい 
※ 条件によります(雑だw) 
• 超々重量級WAFで、一切調整しないと一桁と 
か
さて、ちょっとこれをみてくれないか
Perl (Plack) 
#!/usr/bin/env perl 
use strict; 
use warnings; 
use utf8; 
use JSON::XS qw(encode_json); 
my $app = sub { 
my $env = shift; 
return [ 
200, 
[ 'Content-Type' => 'application/json' ], 
[ encode_json({ message => 'Hello, World!' }) ], 
]; 
}; 
return $app; 
変哲のない生PlackなHelloWorldウェブアプリ
突然ですがベンチマーク 
• 環境 
• Vultr (VPS) の下から二つ目のプラン 
• 1コア (Vultr Virtual CPU 3392Mhz) 
• Mem 1024MB、SSD 
• CentOS6
Perl 5.20.0 
start_server --port=5000 --backlog 16384 
-- plackup -E production -s Starlet --max-keepalive- 
reqs 1000 --max-reqs-per-child 
50000 --min-reqs-per-child 40000 --max-worker 
1 -a ./helloworld.psgi 
ab -n 10000 -c 10
result - perl 
Server Software: Plack::Handler::Starlet 
Server Hostname: 127.0.0.1 
Server Port: 5000 
Document Path: / 
Document Length: 27 bytes 
Concurrency Level: 10 
Time taken for tests: 1.606 seconds 
Complete requests: 10000 
Failed requests: 0 
Write errors: 0 
Total transferred: 1670000 bytes 
HTML transferred: 270000 bytes 
Requests per second: 6225.76 [#/sec] (mean) 
Time per request: 1.606 [ms] (mean) 
Time per request: 0.161 [ms] (mean, across all concurrent requests) 
Transfer rate: 1015.33 [Kbytes/sec] received
result - perl 
Concurrency Level: 10 
Complete requests: 10000 
Requests per second: 6225.76 [#/sec] (mean)
「我がPerlは6000超え、PHPはどうだね?」 
『PHPは遅い…でも武器を手に入れたんだぜ!』 
「なんだと?」 
『PHPだってサーバーになれるんだ!!』 
「フッこざかしい、見せてみろ」
PHPの武器 
libev
php + reactPHP 
<?php 
require_once 'vendor/autoload.php'; 
$app = function (ReactHttpRequest $req,ReactHttpResponse $res) { 
$res->writeHead(200, ['Content-Type' => 'application/json']); 
$res->end(json_encode(['message'=>'Hello World'])); 
}; 
$loop = ReactEventLoopFactory::create(); 
$socket = new ReactSocketServer($loop); 
$http = new ReactHttpServer($socket); 
$http->on('request', $app); 
$socket->listen(5000); 
$loop->run();
PHP 5.6.0 
php boot.php 
ab -n 10000 -c 10
result - php + reactPHP 
Server Software: 
Server Hostname: 127.0.0.1 
Server Port: 5000 
Document Path: / 
Document Length: 36 bytes 
Concurrency Level: 10 
Time taken for tests: 3.397 seconds 
Complete requests: 10000 
Failed requests: 0 
Write errors: 0 
Total transferred: 1420000 bytes 
HTML transferred: 360000 bytes 
Requests per second: 2943.53 [#/sec] (mean) 
Time per request: 3.397 [ms] (mean) 
Time per request: 0.340 [ms] (mean, across all concurrent requests) 
Transfer rate: 408.18 [Kbytes/sec] received
result - php + reactPHP 
Concurrency Level: 10 
Complete requests: 10000 
Requests per second: 2943.53 [#/sec] (mean)
「なんだこの無様な値は」 
『…こんなハズでは…PHPerに未来はないという 
のか!?』 
「ISUC○Nでハブられるような言語がパフォーマ 
ンスに口出しするなど10年速い、言語を変えて出 
直してこい」 
「いや!言語は変えない…俺はPHPerだ!!」
PHPの最終兵器 
HHVM
HipHop VM 3.1.0 
hhvm boot.php 
ab -n 10000 -c 10
result - HHVM 
Server Software: 
Server Hostname: 127.0.0.1 
Server Port: 5000 
Document Path: /index.php 
Document Length: 36 bytes 
Concurrency Level: 10 
Time taken for tests: 1.230 seconds 
Complete requests: 10000 
Failed requests: 0 
Write errors: 0 
Total transferred: 1420000 bytes 
HTML transferred: 360000 bytes 
Requests per second: 8132.90 [#/sec] (mean) 
Time per request: 1.230 [ms] (mean) 
Time per request: 0.123 [ms] (mean, across all concurrent requests) 
Transfer rate: 1127.81 [Kbytes/sec] received
result - HHVM 
Concurrency Level: 10 
Complete requests: 10000 
Requests per second: 8132.90 [#/sec] (mean)
8132.90 [#/sec]
「さっきHHVMはお勧めしないとかいってたじゃ 
ねーか!」 
『手段を選んでいる場合ではなかった!』 
「貴様には矜持というものはないのか!!!」
『某有名パンダの人も言っていた 
 …ような気がする…んだが、 
 得意な言語で勝負はきまらないんだ!』 
※意味が違う
「…ところで、これはどこで実際につかわれてる 
んだ?」 
『これはベンチ番長で、reactPHP(のhttpd)を 
本番に使う度胸はない』 
「えっ」 
『本番は普通にHHVMをhttpdモード(等)でつか 
う』 
「えっ」 
(※reactPHPのhttpdは機能が全くもって不足 
(POST周りとかChunckedとか))
HHVM httpd 
hhvm -p 5000 -m s 
ab -n 10000 -c 10 
index.php 
<?php 
header('Content-Type: application/json'); 
echo json_encode(["message" => 'Hello, World!']);
HHVM httpd result 
Server Software: 
Server Hostname: 127.0.0.1 
Server Port: 5000 
Document Path: /index.php 
Document Length: 27 bytes 
Concurrency Level: 10 
Time taken for tests: 1.704 seconds 
Complete requests: 10000 
Failed requests: 0 
Write errors: 0 
Total transferred: 1240000 bytes 
HTML transferred: 270000 bytes 
Requests per second: 5868.96 [#/sec] (mean) 
Time per request: 1.704 [ms] (mean) 
Time per request: 0.170 [ms] (mean, across all concurrent requests) 
Transfer rate: 710.69 [Kbytes/sec] received
HHVM httpd result 
Concurrency Level: 10 
Complete requests: 10000 
Requests per second: 5868.96 #/sec
「6225.76と5868.96で、負けとるやんけ」 
『普通にやったんじゃPerlには勝てなかった 
よ…』
• 『PHPは(それなりに)速いですが、リクエス 
ト毎に全てをディスポーズするイミュータブル 
世界観による限界が…』 
• 「それこそがPHPの特徴だろ?」 
• 『php-pm(reactPHPをワーカにしたプロセス 
マネージャ)に夢を感じる』 
• こういう話好きな人友達になってください。
まとめ 
• VPS&ローカルab => 計測誤差あるやろ 
• jsonのエンコードベンチ => マシなベンチを 
• 「実用的なものでなく、ベンチ番長で勝ってな 
んの意義があるのか?」 
『チャレンジしたい(という強い心)』
• 実は「kazeburoパラメタ」をオフにすると勝 
ってた(5000くらいになる) 
(start_server --port=5000 --backlog 16384 -- 
plackup -E production -s Starlet -a ./hw.psgi) 
http://www.slideshare.net/kazeburo/ 
yapcasia-2014lttfb 
(Max-workerは1コアなので効果無かった) 
• (上のLTの後で良かった、危ない) 
• kazeburoさんには勝てなかったよ…(違
それPHP? 
↓ 
それはもはやPHP 
(テンプレートエンジン)ではない
まとめのまとめ 
• PHPはWEB向けなら手軽です 
• 今なら道具もそろっている 
• 今風の書き方もできる 
• 皆さんなら、いいPHPコードが書けるでしょう 
• (ダークサイドにおちなければよい) 
• 「それなりな」速度出るぞ 
• ズル(?)すればさらに上も狙える
さて、こんなPHPをおぼえたいなら? 
(経験者向け)
php the right way 
http://ja.phptherightway.com/ 
安心の日本語翻訳です。ここをよめばとりあえず 
最初迷わないでしょう。 
PerlMongerの人はこれだけ覚えて帰って下さい。 
(ちなみに、PHPの情報を集めるなら、 
できれば海外の物が良いでしょう… 
まあ、海外もスットコな情報多いですが)
基本的に以上ですが…時間は 
あまっている? 
One more thing「s」 
または 
質問タイム 
ーーーーーーーーーーー 
YAPC登壇者3人+パーフェク 
トRuby執筆者1人が書いた 
「Webアプリケーション 
エンジニア養成読本」 
好評発売中!
ゆるふわ暗黒PHP
「こんなの暗黒か?PHPerは息をするように避け 
てるぞ」 
と思いますけど、この間あるPerlMongerに話し 
たらウケた内容多めです。
自動変換の闇
有名なPHPの自動変換ですね。 
true == "1" // true 
true == "0" // false 
true == "-1" // true 
true == "" // false
皆様『PHPクソだな^^』
まあ自動変換つかわなきゃいい 
true === "1" // false 
true === "0" // false 
true === "-1" // false 
true === "" // false 
true === true // true 
"1" === "1" // true 
※ しかし、例えばin_array()とか既存関数内の 
マッチは==が… 
(ウウウゥ~!!)
「そもそも1がtrueとかあり 
えないでしょwワロスw」 
  
『それ絶対JSON::xx::true 
周りの事知ってて言ってるで 
しょ!!!』
閑話休題 
0+"1" => int(1) 
0+"a1" => int(0) 
0+"1a" => int(1) 
0+".1" => double(0.1) 
0+"1." => double(1); 
PHPは文字列を数値にキャストするとき、先頭に 
ある数字的な文字だけを拾う…まあギリギリ? 
…だけとおもいきや。
これだ。 
0+"0e" => int(0) 
0+"0e0" => double(0) // <-- ??? 
0+"2e2" => double(200) // <--!? 
0+"0XF" => int(15) // <--!? 
数字の後にeやxがくると別の数値表現として解釈
「ウーーッ!!」 
(突如泡を吹いて倒れるPerlMonger)
はい
自動変換とは違うけど 
シンタックスが…な件
print "a" . 1; // => "a1" 
…まあ普通?しかし…
print "a" . 1; // => "a1" 
! 
print "a".1; // Syntax Error 
「突然のエラー」 
『冗談でしょう!?』
"a" .1; // NG(Syntax Error) 
"a". 1; // OK => "a1" 
『ハァ!?』 
「ほら、.1は数値リテラルだから…」 
『なるほど!?いやダメでしょこれ!?』
現在のみなさんの脳内 
「PHP最悪ですね!^^」
「かかったな!」
Perlも.1が「先頭だと」0.1あつかい 
$ perl -e "print .1;" 
0.1
余談ですが... 
#!perl 
@a = (1); 
print (1 .@a); # ok ==> 11 
print (1.@a); # NG 
まあ、言語って難しいですね。 
(別にどうという話ではない)
はい
いわゆるsplitの闇
"1234" => ["1","2","3","4"] 
としたい、よくありますね。 
PHPでこれはどうやるか?
最初にみつかるexplode() 
文字列を文字列により分割する 
例: explode("", "1234"); 
=> エラーになる、空文字不許可 
残念
それstr_split() 
— 文字列を配列に変換する 
例: str_split("1234"); 
=> OKとおもいきやマルチバイト非対応 
残念
(ちょっと詳しい人なら) 
『えっ、mb_str_split()ある 
んでしょ?』 
「無い!!!」
mb_split() はどうか? 
マルチバイト文字列を正規表現により分割する 
php> var_dump(mb_split('', '1234')); 
array(1) { 
[0] => 
string(4) "1234" 
} 
=> ダメ。しかもeregっぽいし… 
残念
php.netを見ると… 
アホか!!!!!
「使い物にならんものばっかりや…」
正解 preg_split() 
正規表現で文字列を分割する 
preg_split('//u', "あいう", -1, PREG_SPLIT_NO_EMPTY) 
※//uはUnicode扱うやつです。
php > var_dump(preg_split('//u', "あいう", -1, PREG_SPLIT_NO_EMPTY)); 
array(3) { 
[0] => string(3) "あ" 
[1] => string(3) "い" 
[2] => string(3) "う" 
} 
php > var_dump(preg_split('//u', ""/*空文字*/, -1, PREG_SPLIT_NO_EMPTY)); 
array(0) { 
} 
期待通りの結果です! 
「…なんかながくね?うしろのいらなくね?」
外すと奇行に走り出す… 
php > var_dump( preg_split('//u', "あいう") ); 
array(5) { 
[0] => string(0) "" // < -- なにこれ 
[1] => string(3) "あ" 
[2] => string(3) "い" 
[3] => string(3) "う" 
[4] => string(0) "" // < -- なにこれ 
} 
php > var_dump( preg_split('//u', ""/*空文字*/ ) ); 
array(2) { 
[0] => string(0) "" // < -- なにこれ 
[1] => string(0) "" // < -- なにこれ 
}
なので -1, PREG_SPLIT_NO_EMPTYは必要です… 
他の言語ならめっちゃ短くかけるのに、どうして 
こうなった?? 
「オプションの長さなら、json_encodeも負けて 
ないぞ!」 
<?php 
json_encode($data, 
JSON_HEX_TAG | JSON_HEX_APOS | JSON_HEX_AMP | 
JSON_HEX_QUOT | JSON_BIGINT_AS_STRING | JSON_PRETTY_PRINT );
はい
返値の謎
PHPにも返値はあります。本当です。 
※ CLI、Cronとかで実行するときとかちゃんと見 
ますよね? 
例 
die(); 
exit(1); 
安心してください、0と1が返ります。 
※ 二つはエイリアスです
実例 
$ cat exit.php 
<?php 
exit(1); 
$ php exit.php 
$ echo $? 
1 
正気ですね。
exit("1");
$ cat exit.php 
<?php 
exit("1"); 
$ php exit.php 
1 < --- なにこいつ? 
$ echo $? 
0
exit(true); 
(まあこんなのやらんけど)
$ cat exit.php 
<?php 
exit(true); 
$ php exit.php 
1 < --- ウワァァァッァァァァ!?!?! 
$ echo $? 
0 
( 単にboolのtrueをintでキャストすると1になるだ 
けなんですけどね(多分) )
はい
PHP.netの闇
「http://php.netよくできてる」 
と、比較的多くの方から言われますね。 
しかし「User Contributed Notes」 
は参考にしてはならない常識 
ところで最近PHP.netがリニューアルされて少し 
対策されました。
「評価低いやつ、色が薄くなってる…」
はい
まとめ 
• 以上、氷山の一角でした。 
• 「危険PHP」を(訓練された)PHPerは書かない 
• 「安全PHP」書けばいい! 
• 疑ってかかれば大丈夫 
• preg_splitとかは暗記すればいい
皆様『覚えたくないよ!』 
私「はい」
はい
異常でした
以上です 
どうですか?ゆるふわ暗黒話で、最初の方を全部 
忘れている人がいたら悲しいですね。 
これを機会に一人でもPHPを使って見たいと思っ 
て頂ければ幸いです。 
トークの投票が好評なら来年もがんばります(?)
ご静聴有り難うございました 
きたれ! Hachioji.pm 
Perl,PHP,Javasript,Java(スマホ)等 
http://hachiojipm.org/ や @hachiojipm
質問ありますか? 
  
YAPC登壇者3人+パーフェク 
トRuby執筆者1人が書いた 
「Webアプリケーション 
エンジニア養成読本」 
好評発売中!
おまけ 
(誰も質問とかしてくれなくて、はやく終わった 
らやる)
余談:namespaceがが区切り文字 
ということは… 
<?php 
namespace ¥¥{ 
class ¥{ 
static public function ¥(){ 
echo " is not ¥".PHP_EOL; 
} 
} 
} 
namespace { 
¥¥¥::¥(); 
} 
こういうコードが可能なので…
Meanwhile in windows 
Windowsの一部のフォントはツライかもしれませ 
んね! 
(こんなの書く人いないでしょうけど)
関数名変数名に寿司もビアもいけるぞ! 
PHPたのしいですね!!
エラー処理の闇 
というか仕様
PHPの「エラー」 
• (スタートアップエラー) 
• 実行時エラー 
よく画面にでてるNoticeとかFATALとかのやつ 
• 例外 
(※ E_USER等のエラーの話はしません)
実行時エラーの闇 
• よくPHPサイトで出てくるエラーの事です 
• 画面に出す/出さない設定が可能 
=> エラーログには出る 
• エラーレベルの設定も可能 
• NOTICEやDEPRECATED等は終了しない 
=> (意図的に無視するPHPerの存在) 
• ERROR、PARSEなどは強制終了される
ゆるふわPHPerの例 
• 「エラー消せました!^^シェアします!」 
• 「@」やerror_reportingでエラーレベルを変 
更してエラーを握りつぶす 
• display_errorsで「画面から隠す」 
=> エラーログが数ギガとかになる&見ない 
そう言う方々は無視するにせよ、PHPにはPerlの 
use strict、use warningsが無いのが不便… 
(軽いエラーでも終了してくれる)
無いならつくろ!! 
set_error_handler( 
function ($errno, $errstr, $errfile, $errline){ 
echo("エラーだ~!ボク死ぬね^^!"); 
exit; 
} 
); 
エラーがきたら => 死ぬ 
※適切に引数を表示したりerror_logしたりすると 
良いでしょう;
エラーハンドリングの仕様の話 
• 前述の通り、自前のエラーハンドリング関数が 
は登録できる 
• が、場所によって頻繁に差し替えるのはダルい 
=> ログや、詳細を抑制位にしかつかいづらい 
• 例外みたいにつかいたいよーー 
=> 例外に変換しよう!!
例外に変換だ!!! 
set_error_handler( 
function($errno, $errstr, $errfile, $errline){ 
throw new ErrorException( 
$errstr, $errno, 0, $errfile, $errline 
); 
} 
); 
「ヤッタッ!これで例外に統一できる!!」
これで完璧…? 
• 自前エラーハンドリング関数は作れた 
• 例外に変換とかもできた 
• 「これで制覇した??!!」 
• んなわきゃーない
残念仕様でてきたぞー^^ 
• FATAL(関数無いとか)やPARSEなどの強いエラ 
ーはトラップできない 
• ログもエラーメッセージを出す事すらできない 
=> 「白い画面」がでてお客さんがおこ!!! 
=> そして闇っぽい解決策へ…
闇っぽい解決策 
• register_shutdown_function() 
関数登録するとスクリプト終了時にコール 
• FATALなエラーで死ぬ時も呼ばれる 
• そこで「最後のエラーコード」を見て、エラー 
っぽいならエラー処理をする 
• 「なにをいってるんだこいつは??」
例 
register_shutdown_function( 
function(){ // <-- スクリプト終了時に必ず呼ばれる 
$e = error_get_last(); // <-- 前のエラーをひろって 
if( $e['type'] == E_ERROR || // <-- 内容を見てよしなに… 
$e['type'] == E_PARSE || // NOTICEとかは抜いてます 
$e['type'] == E_CORE_ERROR || 
$e['type'] == E_COMPILE_ERROR || 
$e['type'] == E_USER_ERROR ){ 
echo "致命的なエラーが発生しました。n"; 
error_log("ERROR:". 
"/t:{$e['type']}/m:{$e['message']}". 
"/f:{$e['file']}/l:{$e['line']}"); 
} 
} 
); 
※正常終了時も無駄に呼ばれます
やってられるか!!! 
• といいつつやる、結局定型だし。 
• PHPのエラー処理を真面目に書くのはしんどい 
• そもそも、Fatalとか自分のコードが悪い 
• そもそも例外に統一してほしい… 
• エラーハンドラでFATALも扱いたい…
はい
パターンマッチの闇 
ともいいづらい闇
「/(.*)-(.*)/ で "2014-8"をキャプチャした 
い」
/(.)-(.)/ < よくある
preg_match()をつかえばよい 
php > var_dump( 
preg_match("/(.*)-(.*)/u", "2014-8", $_) 
); 
int(1) 
php > var_dump( $_ ); 
array(3) { 
[0] => string(6) "2014-8" 
[1] => string(4) "2014" 
[2] => string(1) "8" 
} 
$_がPerlの$+{~}みたいなわけですね 
まあよさそう
でもダメかもしれない 
存在しない$_をいきなり渡してる。 
(phpにmy(宣言)は無い) 
preg_match( 
"/(?year.*)-(?month.*)/u", 
"2014-8", 
$_ /*<--こいつ*/ 
) 
ちなみにE_NOTICEではない。 
でもちょっと前の静的解析ツールは怒る。
よくある折衷案 
php > $_ = []; // <--非常に無駄な空配列代入 
php > var_dump( 
preg_match("/(.*)-(.*)/u", "2014-8", $_) 
); 
int(1) 
php > var_dump( $_ ); 
array(3) { 
[0] => string(6) "2014-8" 
[1] => string(4) "2014" 
[2] => string(1) "8" 
}
ダサい
はい

YAPC::Asia 2014 - 半端なPHPDisでPHPerに陰で笑われないためのPerl Monger向け最新PHP事情