Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.

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

43,484 views

Published on

YAPC::Asia 2014にてトークした、Perl Monger向けのPHP紹介トークのスライドです。

Published in: Software
  • Be the first to comment

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

  1. 1. 半端なPHPDisでPHPerに陰で笑われないための Perl Monger向け最新PHP事情    YAPC::Asia 2014 @uzulla
  2. 2. Breaking news (このタイミングでリリース…)
  3. 3. Meanwhile in YAPC::Europe 2014
  4. 4. I am ... @uzulla Hachioji.pm PHPer
  5. 5. I ❤️ PHP
  6. 6. 皆さんに質問 PHPを使っている人?
  7. 7. PHPに苦しめられ ている人? DISりたくてここに いる人?
  8. 8. Do you know PHP ?
  9. 9. PHP is ... ? • Webに特化 • LAMPというありふれた環境 (Linux Apache Mysql PHP) • 初心者でもイケるゆるふわなコード • 「Wordpress」「ECCUBE」 「phpMyAdmin」等といった超有名アプリ
  10. 10. PHP is .... ? • レンタルサーバー(レン鯖) • FTPでデプロイ • 関数のかたまり • レガシーコードがやばい • テンプレートエンジン(笑)
  11. 11. Q: PHPはテンプレートエンジ ン? A: はい PHP: Hypertext Preprocessor
  12. 12. ... <div id="user_name"> <?php echo $_GET['name']; ?> </div> ...
  13. 13. Q: DBつかえるってきいたけ ど? A: 勿論です Mysql,sqlite,Pgsql,Oracle,Sqlserver ...
  14. 14. 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>
  15. 15. 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>
  16. 16. …もう帰りたい? (NAOYAさんの発表が裏ですよ!)
  17. 17. MODERN PHP ?
  18. 18. MODERN PHP (probably) • オブジェクト指向プログラミングを駆使 • イケてるライブラリを使う • 「Herokuにデプロイ」 • 「継続的テストも必須だよね」 • とかなんやかんや、やる感じ 個人差有ります
  19. 19. Q: まって、テンプレートエン ジンじゃないの?
  20. 20. Q: まって、テンプレートエン ジンじゃないの? A: PHPはクラス、インターフェイス、抽象クラ スと基本からはじまり、単一継承ではあるものの Traitによって柔軟さを確保し、例外機構、 Finalizeなどもきちんと存在し、簡単なメタプロ もできる程度のマジックメソッドを持ったオブジ ェクト指向プログラミング対応のテンプレートエ ンジンです。
  21. 21. A『は?飛躍したぞ?』 B「OOPって =& のこと?」 C『PEARのことでしょ?』
  22. 22. 論よりナントカ 百聞は一見にしかず とりあえずウェブアプリケーションを作ってみま す。残念ながらライブではありません。
  23. 23. はじめる前に • Windows > PHPはいってない (XAMPPとかWebmatrixとかで入る) • Linux > (Cent5以外なら)AptとかYumとか • Mac > 「それマヴェリック?もう5.4はいって るよ!!」 Macの人はすぐにできます
  24. 24. そんなに慌てて PHPを削除しない でください
  25. 25. 1,ディレクトリ作ります
  26. 26. 2,Composerをいれます。 ワンライナーで入る。 ComposerはPerlで言う所のcpanmみたいなパッ ケージマネージャです。
  27. 27. 3,おもむろにWAFをインストールします。 ※今後php composer.pharをcomposerとタイプ します
  28. 28. 4,コードを書く $ (vim|emacs) index.php
  29. 29. 5,PHPでサーバーをたてる • plackupみたいなの(開発のみに使う) • PHP>=5.4からhttpdが組み込み • コンソールに色つきログが出て便利 • (余談:HTML開発にもつかえる)
  30. 30. 6,hello world! Tadaa!!!できた!!! (Composerを手元で走らせて全部あげれば、世 の中の90%(適当)の実行環境であるレンサバでも 問題ありません)
  31. 31. 繰り返しになりますが Macをお使いの皆さんは • 宗教上の理由 • お医者さんに止められている • 家族の薦め、死んだ婆さんの遺言 とかないかぎり今すぐ使えますよ! 言い訳はできません
  32. 32. PHPのOOPの話
  33. 33. …の前に、クラスのロード方法 • 古代:全部コピペ(そもそも非クラス) • 昔 :先頭に大量のrequire_once() • 近代:自前でオートローダーを実装 • 現代:PSR-0,4対応のローダー (主にComposerの機能) (番外 PEARはinclude_path)
  34. 34. Composerのオートローダーの設定 composer.json修正→composer update(等)
  35. 35. Composerのオートローダーの利用 <?php require_once('vendor/autoload.php'); vendor/autoload.phpをrequire_onceするだけ
  36. 36. クラス名、ファイル名規約、 PSR-0(または4) • 昔は規約なんてなかった、カオスだった • Net_Services_Twitterとか…(長い) • 今はネームスペースを使う • ネームスペース例 UzullaMyLibrary • それに対応するファイルパス例 /path/to/lib/Uzulla/My/Library.php
  37. 37. 「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に秩序を
  38. 38. さっさとOOP はい
  39. 39. こういう感じのファイル配置 (PSR-4だとYapcはショートカットできるけどわか りやすさの為)
  40. 40. コントローラーのベースクラスがこんなんで Yapc/Controller/Base.php <?php namespace YapcController; use SlimSlim; class Base { protected $slim; public function __construct(){ $this->slim = Slim::getInstance(); } }
  41. 41. 継承したクラスはこんなんです Yapc/Controller/Index.php <?php namespace YapcController; class Index extends Base { public function run(){ $this->slim->render('template/index.twig'); } }
  42. 42. 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;
  43. 43. PHPのOOP…これは… • JavaっぽいのOOP、Blessみたいなのはない • 「OOPの本」とかの例が(ある程度)書ける
  44. 44. つまり怖くない 気付いてる人は気付いてると思いますが、 PHPはHTMLのテンプレートエンジンですが、 PHPのコード内にはHTMLは一切かかず、 普通のプログラミング言語のフリをして使うのが 今の書き方です。
  45. 45. Q: じゃあHTMLはどこに書くの? A: テンプレートエンジンである所のPHPで書か れた、別な安全なテンプレートエンジンを使うと 良いでしょう!! 冗談ではありません。 PHPはHTMLの中でいきなりDBにSELECTとかで きて強力すぎるし、オートエスケープがないの で、正しく安全に使うのは非常に面倒。 なので、Twigとかつかうべきでしょう。
  46. 46. Type Hinting function ( MyClass $my_class_instance ){ • 引数の「型」っぽくクラス名書ける • クラス名、インターフェイス名、array等 • 間違えると例外が上がって安心 • 静的解析がはかどる =>IDEが補完ガンガン(超重要)
  47. 47. でも…残念… • integer、Stringなどのスカラ型がない • traitもダメ ※PHP.netでRFCにはなってるのでいつかは… (でも「…そうか…」という箇所もある) https://wiki.php.net/rfc/ scalar_type_hinting_with_cast
  48. 48. 独自例外クラス <?php namespace Yapc; class MyException extends Exception { public function scream(){ echo "うぎゃ~"; } }
  49. 49. 独自例外クラスをキャッチと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 "終わりだ…"; }
  50. 50. SPL • Standard PHP Library • 色々な継承に使えるテンプレートがある • イテレータとかイテレータとか • 継承でForeachにわたせるようになるとか • 例外とか例外とか例外とか • 独自例外つくるより選ぶ方が楽
  51. 51. 他にも… • __set(),__get()、__toString()、 __clone()等の少々のマジックメソッド • final指定 • trait (多重継承の代用等)
  52. 52. OOPじゃないけど • password_hash (PHP>=5.5) 「PHPerでも」「将来にわたって使いやすい」 「安全な」パスワードハッシュをつくれる • Generator (PHP>=5.5) 巨大ファイルや終わりの不明なデータ処理につ かいやすい。 • [1,2] (配列リテラル)(PHP>=5.4) 昔はarray(1,2)というダサイ記法だった
  53. 53. OOPじゃないけど2 IDEによるリアルタイムLint Typoや未宣言変数の指摘 クラス名の重複や
  54. 54. 未使用変数の指摘 「型」の違う変数の指摘 めっちゃイライラが減る!!! 「自分よりPHPStorm(等)が信用できる」
  55. 55. まとめ • PHPはOOPできるようにがんばってる • 例外とかもちゃんとある • 「Javaっぽい?」 • IDEの静的解析が果てしなく便利 => プロはIDEいらないかもですが => 補完のために自然とクラスを作り出す
  56. 56. PHP5.6 -RC4 now- Released!! Yeah!!
  57. 57. • (割とマニアックな機能追加が多い) • 累乗演算子、GMPの演算子オーバーロード • (constによる)定数宣言で式利用可能に • 可変長引数記法や関数の名前空間、誰得? • 各種制限撤廃は嬉しい (php://input再利用可、 ファイルアップロード2GBの天井消滅) • 「余波で」PHP5.3が終了へ(これは重要)
  58. 58. ライブラリ
  59. 59. 最近のライブラリ事情 • PEARは消滅の流れ(PHPUnit、AWSなど) • Packagist+Composerが台頭 • Packagist.orgのRSSが加速している => PHPのライブラリがドンドンふえている! (=>「ACME」ライブラリも多い…)
  60. 60. Packagist ? • http://packagist.org • ライブラリのリポジトリ(インデクスのみ) • npm,rubygemsと似てる • Composerから利用される • ホストはGithub 95%(適当体感)、残り Bitbucketなど • 登録・投稿に一切の審査無し
  61. 61. 増え続けるパッケージ(2014/08/25) • 「36772 packages registered」 • 「142437 versions available」
  62. 62. http://www.modulecounts.com/
  63. 63. Packagist監視業務は結構たのしい(つらい) • よくわからんWAF • よくわからんORM • よくわからんルーター • よくわからんテンプレートエンジン • 「砂場では?」「スターを見よう…」 • 監視業にはRSSが便利 • Twitter: @call_user_func
  64. 64. 監視おじさんのスターリストから • id:uzullaのGithubのスターリストから抜粋 • ライブラリやツール • 全部試した訳ではない • 趣味、偏りがあります
  65. 65. • 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 鉄板のメール送信するやつ
  66. 66. • 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
  67. 67. • 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的 ライブラリ
  68. 68. • 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
  69. 69. • 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)叩くやつ
  70. 70. • 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」
  71. 71. • 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、更新ほぼない
  72. 72. ライブラリまとめ • かなり面白いライブラリやツール増えた • 「これPHPでやるドメインか??」 • 「ホントに動くのかこれ??」 • Packagistは自分でも気軽に登録できる • 国産ライブラリもっと増えて欲しい
  73. 73. 実行環境
  74. 74. 「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
  75. 75. 「本当の所は?」 実用できるのは以下三つ • 本家PHP • HHVM • ZendServer ZendServerは有料なのでよくわからないけど、プ ロファイラとか、5.3を今後もサポートとか、そ ういう強みがある模様
  76. 76. 本家の特徴 • 本物である • pecl(c拡張)がつかえる • 安定している • mod_phpがある
  77. 77. HHVMの特徴 • 速い • 速い • なんかカッコイイ • httpd 動作可能 • チョイチョイたりない互換性 • Hack langつかえる • 速い
  78. 78. Q: どっちをつかうべきでしょうか? A: 本家です
  79. 79. 本家?HHVM? • どっちか迷う人がHHVMはやめた方が良い • 速度以外のメリットはない(大体倍) • でも、実際のネックはDBとかでしょ? • 「本家でありえない物」も、あまりない (将来永続インスタンスとかでてきたらワンチ ャンあるで) • Hack?使ってる所をまだみたことない
  80. 80. 「ところでLAMPはオワコン?」 「nginx+PHPが今ドキでは?」
  81. 81. Apacheの特徴 • htaccessの楽さ • mod_phpとmod_rewriteの組み合わせは やっぱり柔軟で強力 (FastCGIはURIのマップでかゆいところに手 が届かないか、コンフィグが複雑で面倒) • 手間&手離れ
  82. 82. nginxの特徴 • 特に遅いモバイル相手で裁ける量が違う • 複数アプリを相乗りしだすと色々面倒 (複数のrepoがデプロイされてるとか…) • 協力会社とお客様のご理解 (「なんでhtaccessがないの!?」  「(秘伝のタレ)を置いて下さい」) • 監視点や監視ログが増える
  83. 83. まとめ • 「PHPらしく」つかうとLAMPしかない事も • Apache+mod_phpの楽さ、柔軟さハンパない • nginx+php-fpmは速度が欲しければ良い • nginx+HHVM(fastCGI)は最悪php-fpmに戻せる
  84. 84. それPHP?
  85. 85. PHPの欠点 遅い
  86. 86. 本当なの? • plackで 1000req/s の所 50~300req/sくらい ※ 条件によります(雑だw) • 超々重量級WAFで、一切調整しないと一桁と か
  87. 87. さて、ちょっとこれをみてくれないか
  88. 88. 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ウェブアプリ
  89. 89. 突然ですがベンチマーク • 環境 • Vultr (VPS) の下から二つ目のプラン • 1コア (Vultr Virtual CPU 3392Mhz) • Mem 1024MB、SSD • CentOS6
  90. 90. 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
  91. 91. 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
  92. 92. result - perl Concurrency Level: 10 Complete requests: 10000 Requests per second: 6225.76 [#/sec] (mean)
  93. 93. 「我がPerlは6000超え、PHPはどうだね?」 『PHPは遅い…でも武器を手に入れたんだぜ!』 「なんだと?」 『PHPだってサーバーになれるんだ!!』 「フッこざかしい、見せてみろ」
  94. 94. PHPの武器 libev
  95. 95. 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();
  96. 96. PHP 5.6.0 php boot.php ab -n 10000 -c 10
  97. 97. 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
  98. 98. result - php + reactPHP Concurrency Level: 10 Complete requests: 10000 Requests per second: 2943.53 [#/sec] (mean)
  99. 99. 「なんだこの無様な値は」 『…こんなハズでは…PHPerに未来はないという のか!?』 「ISUC○Nでハブられるような言語がパフォーマ ンスに口出しするなど10年速い、言語を変えて出 直してこい」 「いや!言語は変えない…俺はPHPerだ!!」
  100. 100. PHPの最終兵器 HHVM
  101. 101. HipHop VM 3.1.0 hhvm boot.php ab -n 10000 -c 10
  102. 102. 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
  103. 103. result - HHVM Concurrency Level: 10 Complete requests: 10000 Requests per second: 8132.90 [#/sec] (mean)
  104. 104. 8132.90 [#/sec]
  105. 105. 「さっきHHVMはお勧めしないとかいってたじゃ ねーか!」 『手段を選んでいる場合ではなかった!』 「貴様には矜持というものはないのか!!!」
  106. 106. 『某有名パンダの人も言っていた  …ような気がする…んだが、  得意な言語で勝負はきまらないんだ!』 ※意味が違う
  107. 107. 「…ところで、これはどこで実際につかわれてる んだ?」 『これはベンチ番長で、reactPHP(のhttpd)を 本番に使う度胸はない』 「えっ」 『本番は普通にHHVMをhttpdモード(等)でつか う』 「えっ」 (※reactPHPのhttpdは機能が全くもって不足 (POST周りとかChunckedとか))
  108. 108. 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!']);
  109. 109. 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
  110. 110. HHVM httpd result Concurrency Level: 10 Complete requests: 10000 Requests per second: 5868.96 #/sec
  111. 111. 「6225.76と5868.96で、負けとるやんけ」 『普通にやったんじゃPerlには勝てなかった よ…』
  112. 112. • 『PHPは(それなりに)速いですが、リクエス ト毎に全てをディスポーズするイミュータブル 世界観による限界が…』 • 「それこそがPHPの特徴だろ?」 • 『php-pm(reactPHPをワーカにしたプロセス マネージャ)に夢を感じる』 • こういう話好きな人友達になってください。
  113. 113. まとめ • VPS&ローカルab => 計測誤差あるやろ • jsonのエンコードベンチ => マシなベンチを • 「実用的なものでなく、ベンチ番長で勝ってな んの意義があるのか?」 『チャレンジしたい(という強い心)』
  114. 114. • 実は「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さんには勝てなかったよ…(違
  115. 115. それPHP? ↓ それはもはやPHP (テンプレートエンジン)ではない
  116. 116. まとめのまとめ • PHPはWEB向けなら手軽です • 今なら道具もそろっている • 今風の書き方もできる • 皆さんなら、いいPHPコードが書けるでしょう • (ダークサイドにおちなければよい) • 「それなりな」速度出るぞ • ズル(?)すればさらに上も狙える
  117. 117. さて、こんなPHPをおぼえたいなら? (経験者向け)
  118. 118. php the right way http://ja.phptherightway.com/ 安心の日本語翻訳です。ここをよめばとりあえず 最初迷わないでしょう。 PerlMongerの人はこれだけ覚えて帰って下さい。 (ちなみに、PHPの情報を集めるなら、 できれば海外の物が良いでしょう… まあ、海外もスットコな情報多いですが)
  119. 119. 基本的に以上ですが…時間は あまっている? One more thing「s」 または 質問タイム ーーーーーーーーーーー YAPC登壇者3人+パーフェク トRuby執筆者1人が書いた 「Webアプリケーション エンジニア養成読本」 好評発売中!
  120. 120. ゆるふわ暗黒PHP
  121. 121. 「こんなの暗黒か?PHPerは息をするように避け てるぞ」 と思いますけど、この間あるPerlMongerに話し たらウケた内容多めです。
  122. 122. 自動変換の闇
  123. 123. 有名なPHPの自動変換ですね。 true == "1" // true true == "0" // false true == "-1" // true true == "" // false
  124. 124. 皆様『PHPクソだな^^』
  125. 125. まあ自動変換つかわなきゃいい true === "1" // false true === "0" // false true === "-1" // false true === "" // false true === true // true "1" === "1" // true ※ しかし、例えばin_array()とか既存関数内の マッチは==が… (ウウウゥ~!!)
  126. 126. 「そもそも1がtrueとかあり えないでしょwワロスw」   『それ絶対JSON::xx::true 周りの事知ってて言ってるで しょ!!!』
  127. 127. 閑話休題 0+"1" => int(1) 0+"a1" => int(0) 0+"1a" => int(1) 0+".1" => double(0.1) 0+"1." => double(1); PHPは文字列を数値にキャストするとき、先頭に ある数字的な文字だけを拾う…まあギリギリ? …だけとおもいきや。
  128. 128. これだ。 0+"0e" => int(0) 0+"0e0" => double(0) // <-- ??? 0+"2e2" => double(200) // <--!? 0+"0XF" => int(15) // <--!? 数字の後にeやxがくると別の数値表現として解釈
  129. 129. 「ウーーッ!!」 (突如泡を吹いて倒れるPerlMonger)
  130. 130. はい
  131. 131. 自動変換とは違うけど シンタックスが…な件
  132. 132. print "a" . 1; // => "a1" …まあ普通?しかし…
  133. 133. print "a" . 1; // => "a1" ! print "a".1; // Syntax Error 「突然のエラー」 『冗談でしょう!?』
  134. 134. "a" .1; // NG(Syntax Error) "a". 1; // OK => "a1" 『ハァ!?』 「ほら、.1は数値リテラルだから…」 『なるほど!?いやダメでしょこれ!?』
  135. 135. 現在のみなさんの脳内 「PHP最悪ですね!^^」
  136. 136. 「かかったな!」
  137. 137. Perlも.1が「先頭だと」0.1あつかい $ perl -e "print .1;" 0.1
  138. 138. 余談ですが... #!perl @a = (1); print (1 .@a); # ok ==> 11 print (1.@a); # NG まあ、言語って難しいですね。 (別にどうという話ではない)
  139. 139. はい
  140. 140. いわゆるsplitの闇
  141. 141. "1234" => ["1","2","3","4"] としたい、よくありますね。 PHPでこれはどうやるか?
  142. 142. 最初にみつかるexplode() 文字列を文字列により分割する 例: explode("", "1234"); => エラーになる、空文字不許可 残念
  143. 143. それstr_split() — 文字列を配列に変換する 例: str_split("1234"); => OKとおもいきやマルチバイト非対応 残念
  144. 144. (ちょっと詳しい人なら) 『えっ、mb_str_split()ある んでしょ?』 「無い!!!」
  145. 145. mb_split() はどうか? マルチバイト文字列を正規表現により分割する php> var_dump(mb_split('', '1234')); array(1) { [0] => string(4) "1234" } => ダメ。しかもeregっぽいし… 残念
  146. 146. php.netを見ると… アホか!!!!!
  147. 147. 「使い物にならんものばっかりや…」
  148. 148. 正解 preg_split() 正規表現で文字列を分割する preg_split('//u', "あいう", -1, PREG_SPLIT_NO_EMPTY) ※//uはUnicode扱うやつです。
  149. 149. 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) { } 期待通りの結果です! 「…なんかながくね?うしろのいらなくね?」
  150. 150. 外すと奇行に走り出す… 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) "" // < -- なにこれ }
  151. 151. なので -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 );
  152. 152. はい
  153. 153. 返値の謎
  154. 154. PHPにも返値はあります。本当です。 ※ CLI、Cronとかで実行するときとかちゃんと見 ますよね? 例 die(); exit(1); 安心してください、0と1が返ります。 ※ 二つはエイリアスです
  155. 155. 実例 $ cat exit.php <?php exit(1); $ php exit.php $ echo $? 1 正気ですね。
  156. 156. exit("1");
  157. 157. $ cat exit.php <?php exit("1"); $ php exit.php 1 < --- なにこいつ? $ echo $? 0
  158. 158. exit(true); (まあこんなのやらんけど)
  159. 159. $ cat exit.php <?php exit(true); $ php exit.php 1 < --- ウワァァァッァァァァ!?!?! $ echo $? 0 ( 単にboolのtrueをintでキャストすると1になるだ けなんですけどね(多分) )
  160. 160. はい
  161. 161. PHP.netの闇
  162. 162. 「http://php.netよくできてる」 と、比較的多くの方から言われますね。 しかし「User Contributed Notes」 は参考にしてはならない常識 ところで最近PHP.netがリニューアルされて少し 対策されました。
  163. 163. 「評価低いやつ、色が薄くなってる…」
  164. 164. はい
  165. 165. まとめ • 以上、氷山の一角でした。 • 「危険PHP」を(訓練された)PHPerは書かない • 「安全PHP」書けばいい! • 疑ってかかれば大丈夫 • preg_splitとかは暗記すればいい
  166. 166. 皆様『覚えたくないよ!』 私「はい」
  167. 167. はい
  168. 168. 異常でした
  169. 169. 以上です どうですか?ゆるふわ暗黒話で、最初の方を全部 忘れている人がいたら悲しいですね。 これを機会に一人でもPHPを使って見たいと思っ て頂ければ幸いです。 トークの投票が好評なら来年もがんばります(?)
  170. 170. ご静聴有り難うございました きたれ! Hachioji.pm Perl,PHP,Javasript,Java(スマホ)等 http://hachiojipm.org/ や @hachiojipm
  171. 171. 質問ありますか?   YAPC登壇者3人+パーフェク トRuby執筆者1人が書いた 「Webアプリケーション エンジニア養成読本」 好評発売中!
  172. 172. おまけ (誰も質問とかしてくれなくて、はやく終わった らやる)
  173. 173. 余談:namespaceがが区切り文字 ということは… <?php namespace ¥¥{ class ¥{ static public function ¥(){ echo " is not ¥".PHP_EOL; } } } namespace { ¥¥¥::¥(); } こういうコードが可能なので…
  174. 174. Meanwhile in windows Windowsの一部のフォントはツライかもしれませ んね! (こんなの書く人いないでしょうけど)
  175. 175. 関数名変数名に寿司もビアもいけるぞ! PHPたのしいですね!!
  176. 176. エラー処理の闇 というか仕様
  177. 177. PHPの「エラー」 • (スタートアップエラー) • 実行時エラー よく画面にでてるNoticeとかFATALとかのやつ • 例外 (※ E_USER等のエラーの話はしません)
  178. 178. 実行時エラーの闇 • よくPHPサイトで出てくるエラーの事です • 画面に出す/出さない設定が可能 => エラーログには出る • エラーレベルの設定も可能 • NOTICEやDEPRECATED等は終了しない => (意図的に無視するPHPerの存在) • ERROR、PARSEなどは強制終了される
  179. 179. ゆるふわPHPerの例 • 「エラー消せました!^^シェアします!」 • 「@」やerror_reportingでエラーレベルを変 更してエラーを握りつぶす • display_errorsで「画面から隠す」 => エラーログが数ギガとかになる&見ない そう言う方々は無視するにせよ、PHPにはPerlの use strict、use warningsが無いのが不便… (軽いエラーでも終了してくれる)
  180. 180. 無いならつくろ!! set_error_handler( function ($errno, $errstr, $errfile, $errline){ echo("エラーだ~!ボク死ぬね^^!"); exit; } ); エラーがきたら => 死ぬ ※適切に引数を表示したりerror_logしたりすると 良いでしょう;
  181. 181. エラーハンドリングの仕様の話 • 前述の通り、自前のエラーハンドリング関数が は登録できる • が、場所によって頻繁に差し替えるのはダルい => ログや、詳細を抑制位にしかつかいづらい • 例外みたいにつかいたいよーー => 例外に変換しよう!!
  182. 182. 例外に変換だ!!! set_error_handler( function($errno, $errstr, $errfile, $errline){ throw new ErrorException( $errstr, $errno, 0, $errfile, $errline ); } ); 「ヤッタッ!これで例外に統一できる!!」
  183. 183. これで完璧…? • 自前エラーハンドリング関数は作れた • 例外に変換とかもできた • 「これで制覇した??!!」 • んなわきゃーない
  184. 184. 残念仕様でてきたぞー^^ • FATAL(関数無いとか)やPARSEなどの強いエラ ーはトラップできない • ログもエラーメッセージを出す事すらできない => 「白い画面」がでてお客さんがおこ!!! => そして闇っぽい解決策へ…
  185. 185. 闇っぽい解決策 • register_shutdown_function() 関数登録するとスクリプト終了時にコール • FATALなエラーで死ぬ時も呼ばれる • そこで「最後のエラーコード」を見て、エラー っぽいならエラー処理をする • 「なにをいってるんだこいつは??」
  186. 186. 例 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']}"); } } ); ※正常終了時も無駄に呼ばれます
  187. 187. やってられるか!!! • といいつつやる、結局定型だし。 • PHPのエラー処理を真面目に書くのはしんどい • そもそも、Fatalとか自分のコードが悪い • そもそも例外に統一してほしい… • エラーハンドラでFATALも扱いたい…
  188. 188. はい
  189. 189. パターンマッチの闇 ともいいづらい闇
  190. 190. 「/(.*)-(.*)/ で "2014-8"をキャプチャした い」
  191. 191. /(.)-(.)/ < よくある
  192. 192. 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の$+{~}みたいなわけですね まあよさそう
  193. 193. でもダメかもしれない 存在しない$_をいきなり渡してる。 (phpにmy(宣言)は無い) preg_match( "/(?year.*)-(?month.*)/u", "2014-8", $_ /*<--こいつ*/ ) ちなみにE_NOTICEではない。 でもちょっと前の静的解析ツールは怒る。
  194. 194. よくある折衷案 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" }
  195. 195. ダサい
  196. 196. はい

×