行われたPHPカンファレンス2015で発表をしてきました。スライドは以下の内容です。PHPカンファレンスでは公募セッションは最大30分のため、すべてのページについて話すことができませんした。入門部分を中心に解説しました。このブログでは、スライドの共有と共に、話せなかった部分ついて(とうまくいかなかったデモも)書いておきたいと思います。Composerと、その歴史PHPで開発をするのに、デファクトスタンダードになったといって良いComposer。Composerは2012年3月1日に生まれました。最初のリリース番号は1.0.0のアルファ1です。現在も1.0-devというバージョンで日々アップデートが行われています。2012年というのはすごい最近ですよね。その前はどうだったのか?少しふりかえってみたいと思います。Composerの前はどうだったのか?PHPにはじめて拡張モジュールやライブラリの置き場所ができたのは1999年、pearという名前でした。perlのCPANに影響を受けていて、あくまでコードリポジトリという位置づけでした。Managementであるのとは異なります。2006年にはPHP5.3に対応したpear2とpyrusが登場しました。pearは厳密なコードレビューからオープンソースのリポジトリでありながら「誰もが自由に公開できる場所」とはいいづらいものでした。そこで2008年にnequalが立ち上げたのがopenpearです。pearパッケージを誰もが自由に公開できるような場所となりました。リポジトリはsvnでした。あのsotarokさんのコメントがトップページにあります「夢のような話だ」、まさにそのとおりでした。時代はgit、githubになり、2012年にcomposerが生まれたのです。Composerを正しく理解するComposerはDependencyManagementです。YumやAptといったパッケージ管理とは違います。pearはこちらに近かったかもしれません。npmやbundlerといったものに影響を受けていて、プロジェクト単位で依存関係を管理します。私はどんなプロジェクトでも必ず必要だったのはPHPUnitではないかと思います。pearでやるとかなり面倒なんですよね、複数バージョン入れ分けなくてはいけないなんて事はなかったですか?(地獄でしたよねw)昨年、PHPUnitはPEARから卒業しました。スライドではそのときのSebastionBergmannのツイートを引用しました。最近サルベージしたので、アイコンは当時写真だったと思うのですが、今はイラストですね(良く似ていますww)。具体的には、csvから始まって、pearに移って、2009年にはgithubに移って、今日ではpearから卒業する、長らくありがとうという内容です。PHPUnit3.7.0からComposrで取得可能です。PHPUnitを例にとって、Composerより前はどんな方法だったか思い出してみましょう。スライドではPHPUnitのpearを使った導入方法を掲載しました。1つ1つはもう気にしなくて良いのですが、長いですよね。秘伝のレシピにしているか、ググってコピペするか、会社でドキュメント化しているか、そんなところだったと思います。秘伝のレシピの場合、もちろんコマンド1つかもしれないですが、初めてプロジェクトに入った人がわかるわけではないですね。複数バージョンを同居させるとかになると、pyrus使ったりしてもう少し違う感じにはなるかと思います。あと、iniのインクルードパスを設定しないとファイルが読み込めなかったですよねComposerになった(今どきの)やり方Composerになって、初めて入れるときはrequire、他の人はinstallコマンドを実行するだけで良くなりました。簡単なんだろう、環境設定マニュアルとか必要ないレベルですよね。cloneしたリポジトリにcomposer.jsonがある段階でinstallを実行するはずです。–devじゃないとか?いうのはそのとおりですが、今回は省略しています)PHPで正しく開発するには今日ではこのようにPHPでもモダンな開発をするベースが整っています。Wayというページに、そのすべてがまとまっています。Composerについても書いてあります。PHPerが幸せになる為の道しるべを示してくれています。各国の有志によって翻訳されているので、すぐ読めます。使ってみたかっただけで、深い意味はありません。Wayではコーディングスタイルや名前空間といったことにも言及しています。どちらにもPSR-4という記述がありますが、PSR-4はオートロードについての標準です。現在はPSR-0を含んでいるので、PSR-0でなくPSR-4を参照するのが良いでしょう。オートロードとComposerの関係についてPHPでクラスをオートロードするには、_autoloadを実装して、クラスが見つからないときに指示してあげるか、splautoload_registerで予めクラスのパスを登録しておくという2通りのやり方があります。「ちなみにこの方法でオートロードを実装したことがある人はいますか?」という問いにはどなたも手があがりませんでした。これはそのとおりだと思います。Composer以前ではほぼ気にする人はいなかったでしょう。フレームワークを使ってアプリケーションを実装している人は、フレームワークがオートロードの仕組みを用意してくれていたりするので、より意識しないかなと思います。デモ本番ではうまくいかなかったのですが、こちらで解説します。(カンファレンスあるあるですね)インストールスライドの内容を参考にcomposerをインストールします。composerはプロジェクトのローカルでなく、パスの通っているところに配置してください。Wayにも書いてあります。Windowsを利用の方は公式ドキュメントを参照ください。GitHubのリポジトリからソースコードを取得します。initコマンドでプロジェクト情報を入力します。requireやrequire-devは必要ないので、noを入力すれば大丈夫です。installコマンドを実行します。最初は何もありません。vendorディレクトリが生成されるはずです。いうコマンドを実行します。ブラウザからサンプルページを実行してください。次にSay\Helloクラスを実行してみます。/helloにアクセスします。19というエラーが表示されるはずです。ソースコードでは以下のように指定していますが、オートロードが定義されていないのでクラスは見つかりません。Say\Hello;そこで、composer.jsonを編集して、以下のようにrequireの下に追記します。いうコマンドを実行します。再度Say\Helloクラスを実行してみます。/helloにアクセスします。すると、ブラウザにHelloと表示されるはずです。今度は/emojiにアクセスします。先ほどと同じようなエラーが表示されるので、composer.jsonを編集します。いうコマンドを実行します。再度Write/Emojiクラスを実行してみます。/emojiにアクセスします。すると、ブラウザに(^o^)と表示されるはずです。このようにオートロードについて自分で記述しなくても、名前空間の宣言をcomposer.jsonでおこなうと自動的にクラスをロードしてくれるようになります。Tipsこの先は解説できなかった部分なので補足します。PHP勉強会@東京〜PHPカンファレンス2015開催直前スペシャル〜で話しました。スタジオアルカナのレポートに詳しいログが残っていますので、そちらを参照ください。スクリプトComposerの強力な機能にスクリプト(フック)の実行があります。installやupdateなどcomposerのコマンド実行前と実行後に、スクリプトを実行できます。pre-install-cmdpost-install-cmdのようなイベント名です。実行できるスクリプトは通常のCLIとPHPのクラスです。以下のように記述します。],より詳しい情報は公式サイトを参照して欲しいのですが、これの使い方は2つ考えられます。1つ目は、すでに存在するライブラリに対するプロキシとしたい場合です。公開されているライブラリをForkしたり、コピーしてくることなく、独自の変更を加えたい場合や、ライブラリをインストールした後で独自のconfigを追加したい場合など、社内で複数のプロジェクトにまたがって同じカスタマイズをしたい場合は有効です。それぞれのプロジェクトではプロキシしたcomposer.jsonのあるリポジトリを指定するだけで、元のライブラリを修正することなく、同じようにカスタマイズ状態を利用できます。2つ目は、フレームワークやライブラリを作った場合です。create-projectに対応したスケルトンを用意しています。何もなければそれを取得すれば良いのですが、もちろんcreate-projectコマンドにもフックポイントが用意されているので、install後には環境設定ファイルなどがコピーされるようになっています。まとめこのようにComposerはpearでできていたパッケージ(コードリポジトリ)管理から、より多くの機能を持って、現在のアプリケーション開発になくてはならないものとなっています。このセッションでComposerを使うようになってくれる人が増えることを期待してまとめとしたいと思います。おまけLTのスライドも公開します。PMPHPこの記事は先日の正規表現を簡単に作るにはの続編になります。Expressionの既存実装でやろうとすると、うまくできないという問題に直面しました。そこでRubyで実装されていたHEXPRESSをPHPへ移植しようという流れです。PHP版Hexpressを作ったさっそく移植してみました。hexpressPSR-2の対応が実施中なのですが、Ruby側の機能とテストはすべて移植し、PHP版でいくつか機能追加をしています。どんな感じかREADMEに書いてあるとおりインストールはcomposer経由でできます。sizuhiko/hexpress具体的な利用方法は以下のサンプルのとおりです。"/^https?\:\/\/(?:(?:\w)+\.)?([\w\-]+)\.(?:com|org)\/?$/"Hexpressクラスのインスタンスを生成して、メソッドチェインで正規表現を組み立てます。それに対してメソッドチェインでつないていきます。Hexpressは__toString()を実装しており、文字列表現を取得すると指定された定義を展開します。実際に正規表現として利用するにはtoRegExp()を呼び出すと、左右にデリミタを挿入した文字列が取得できるので、preg_matchなどの関数で利用可能になります。以下のような利用方法です。$pattern->toRegExp());複雑な正規表現は定義できたのか?できました!!テストコードとしてRFC3986Test.phpを作成しました。RFCに対応した正規表現を構築することができました。(※IPv6の定義は未実装です、ご了承ください)PHPUnitのデータプロバイダexampleUriProviderでマッチさせるパターンをftp,www,mail,news,tel,telnet,urnについて定義してすべて通過しています。PHP版では、マッチするときfindメソッドで名前付きサブパターンを利用できるようにしました。以下の例のように、findの第二引数にportを指定できます。}上記を含むパターンをpreg_matchで処理すると、マッチング結果に名前付きで値を取得できるようになります。'80'どうなのか?たとえば今回作成したRFC3986の定義を正規表現としてダンプすると、以下のようになります。/^(?P<scheme>[a-zA-Z](?:[a-zA-Z0-9\+\-\.])*)\:(?P<hierPart>(?:\/\/(?P<authority>(?:(?P<userinfo>(?:(?:[a-zA-Z0-9\-\._~]|%(?:[0-9A-Z]){2}|[\!\$&'\(\)\*\+,;\=]|\:))*)@)?(?P<host>(?:(?:0-9|1-90-9|10-90-9|20-40-9|250-5)\.(?:0-9|1-90-9|10-90-9|20-40-9|250-5)\.(?:0-9|1-90-9|10-90-9|20-40-9|250-5)\.(?:0-9|1-90-9|10-90-9|20-40-9|250-5)|(?:(?:[a-zA-Z0-9\-\._~]|%(?:[0-9A-Z]){2}|[\!\$&'\(\)\*\+,;\=]))+))(?:\:(?P<port>(?:\d)+))?)(?P<pathAbempty>(?:\/(?:(?:[a-zA-Z0-9\-\._~]|%(?:[0-9A-Z]){2}|[\!\$&'\(\)\*\+,;\=]|\:|@))*)*)|(?P<pathAbsolute>\/(?:(?:(?:[a-zA-Z0-9\-\._~]|%(?:[0-9A-Z]){2}|[\!\$&'\(\)\*\+,;\=]|\:|@))+(?:\/(?:(?:[a-zA-Z0-9\-\._~]|%(?:[0-9A-Z]){2}|[\!\$&'\(\)\*\+,;\=]|\:|@))*)+)?)|(?P<pathRootless>(?:(?:[a-zA-Z0-9\-\._~]|%(?:[0-9A-Z]){2}|[\!\$&'\(\)\*\+,;\=]|\:|@))+(?:\/(?:(?:[a-zA-Z0-9\-\._~]|%(?:[0-9A-Z]){2}|[\!\$&'\(\)\*\+,;\=]|\:|@))*)*)|(?P<pathEmpty>^(?:[a-zA-Z0-9\-\._~]|%(?:[0-9A-Z]){2}|[\!\$&'\(\)\*\+,;\=]|\:|@))))(?:\?(?P<query>(?:(?:(?:[a-zA-Z0-9\-\._~]|%(?:[0-9A-Z]){2}|[\!\$&'\(\)\*\+,;\=]|\:|@)|\/|\?))*))?(?:#(?P<fragment>(?:(?:(?:[a-zA-Z0-9\-\._~]|%(?:[0-9A-Z]){2}|[\!\$&'\(\)\*\+,;\=]|\:|@)|\/|\?))*))?$/私はいきなりこれを空手形で実装することはできそうにないので、今回hexpressを移植して良かったなと思っています。何か複雑な正規表現を定義したい場合などに役立てば幸いです。さいごに日本PHPカンファレンス2015が10/3(土)に行われます。当日のプログラムも公開され、私はトラック3で10:50から11:20まで「Composerではじめるアプリケーション開発」というセッションを担当します。他の番組が強力なため私の会場は比較的空いているのではないかと思うので、もしご都合がつく方はよろしくお願いします。私は好きですが、得意とは言えません。VerbalExpressionという選択肢そこでVervalExpressionという正規表現を簡単に組むことができる仕組みがあります。easy」と書いてあるように、簡単に正規表現が作れることを表明しています。様々な言語にポートされていますが、もちろんPHP版もあります。https://github.com/VerbalExpressions/PHPVerbalExpressionsサイトのサンプルにも書いてあるとおり、以下のようなURLにマッチする正規表現が記述できます。関数でそのまま使えます。スキーマ部分だけ記述してみます。ようになってしまい、期待通りではありません。この実装は入れ子には対応していないようです。1つのVerbalExpression実装PHPにはもう1つ別のVerbalExpression実装があります。https://github.com/markwilson/VerbalExpressionsPhpこちらの実装はREADMEに入れ子について記述されているように、入れ子の対応はされているようです。RFC3986の定義を試してみましょう。ようになってしまい、まぁ不正ではないのですが、かなり無駄があります。現時点結局のところどちらの実装も簡単なパターンをやるときには良いのですが、ちょっと複雑なパターンを実装しようと思うと微妙です。