Technote

by sizuhiko

PHPカンファレンス福岡2016に参加してLTをしました

2016/5/21 に行われたPHPカンファレンス福岡2016に参加してきました。

プロレス大会を思わせるサイトデザインがカッコいい

はじめてのPHPカンファレンス福岡

昨年の第一回は、個人的な年間スケジュールとバッティングしてしまい参加できなかったので、今回が初のPHPカンファレンス福岡です。 福岡はPHP祭り以来で、なんとも久しぶりです。

2012年に開催されたPHP祭り福岡。祭り懐かしい

非公式の前夜祭が行われていたようなのですが、ホテルで翌日のLTネタを仕込んでいたら出遅れたので、近所のエールズで1人前夜祭をしていました。 そのあと、ラムバーに行き、ラーメンを….(ry

PHPカンファレンス福岡2016

会場の「福岡ファッションビル」は祇園駅のすぐ目の前で、とてもわかりやすく、ビルがでかい。 しかも隣にウェストがあるという最高の立地です(ランチ的な意味で)。

イベントは札幌と同じ2トラック+スポンサーブースで、どのセッションも聞きたかったのですが、主にメイン会場にいました。

  • 制約と上手く付き合う
  • ドキュメントを支える技術
  • ロリポップ!で目指す、PHPのためのセキュリティと性能要件を同時に満たすサーバホスティング技術
  • PHPerの皆さまへ!「さくらクラブ」で何か楽しいことしませんか?
  • CakePHP3で学ぶAPIマネジメント
  • 今こそCakePHP3に乗り換えよう!
  • PHPに型推論を実装する
  • 日本で一番PHPのシステムをテストしている手動テスターが思うところ
  • HTTPメッセージ - PHPで扱う場合の再入門
  • Slim3とPSR-7
  • WordPress REST APIが開くWordPressの未来
  • CakePHP3レポート
  • LT

ふりかえるとセッション数多いなー。30分と15分のセッションが1枠の中にセットで入っていたためですが、とにかく目白押しです。

印象的だったことを振り返っておきます。

  • 時間がもっとあると良いと思ったセッションが多かったので、ぜひ続編&長編で聞きたい(東京とか大阪とか…)
  • スポンサーセッションが それっぽくなくて 、福岡PHPコミュニティの懐の深さを感じた
  • CakePHP3の話題が多くて良かった(個人的な感想です)
  • タイムテーブルでどっちも聞きたいという状況があるにはあったけど、ターゲットを想定していい感じに別れていて、スタッフのプログラム構成力に関心した
  • 会場が広くて快適だった。スポンサー様すごい
  • 楽しい!美味しい!(無限コーヒーとか)
  • イベントのライブ感が素晴らしかった
    • メインセッションのアンサーLTが懇親会であった
    • みんなが続きが聞きたいと思ったロリポップのセッションを懇親会LTで最後まで聞けた

盛り上がりは、以下のまとめサイトを参照していただければと思います。

懇親会、乾杯直前。同じ会場で行われたので移動もなく便利

イベントの後は二次会、三次会、ラーメン、Barの順に巡りホテルに戻りました。

福岡はコンパクトで移動が楽だし、美味しいものが多い

前日の懇親会で烏賊ツアーが企画されたので、参加しました。

河太郎福岡駅店にて。マップだとマルイビルを指しているように見えるが、実際はマルイを抜けたJRビルにあるから注意

このあと、フライトまで時間があったので、連泊するという参加者と九州国立博物館と太宰府天満宮へ観光に行きました。バスで40分ぐらい。近い。 太宰府でドローンを飛ばした人がいるのだろうか。まぁ神社とかドローンで動画撮ったら見栄えが良さそう

やはりカンファレンスは生で味わった方がよい

@uzulla さんのイベントレポートPHPカンファレンス福岡2016でイエーイの件、そして遠方カンファレンス参加のススメ。がとても良いので、一読して欲しいのですが、とにかくカンファレンスは生き物です。

今回のイベントは、そういう意味でとてもライブ感があって良かったと思うし、大阪もそれに近いなといつも思っています。 昨年はスケジュールが重なりまくって、遠方カンファレンスには海外へ一度行ったきりでした。楽しかったという話を聞くたびにとても悔しい想いをしたので、今年は全部参加したいと思っています。

旅行と行っても、札幌も福岡もLCC(格安航空)を使えば往復1.5万円ぐらいだし、宿泊しても3万円ぐらいあれば大丈夫です(飲食代は除きます。そっちの方が高いという噂w)。 スライドは公開されるし、Twitterのまとめはスグに出るので、参加していなくてもコンテンツは見れるのですが、言葉,反応,会話はスライドやまとめサイトには含まれません。 公開されたスライドは、参加した人にとってメモしなくて良いとても便利なものなのですが、参加していないセッションのを見ても同じ体験を得ることはできません。

偉そうなこと書きましたが、単にみんなと会って話をしたいだけです。 まだ大阪も東京も、YAP(achimon)C::Asia Hachiojiもあるので、イベントで会いましょう。そして乾杯!

また来年も来れますように

中心地から空港まで地下鉄で2駅という便利さ

札幌からの帰路は関東の荒天に阻まれましたが、今回は晴天のうちに帰宅しました。

LTしました

札幌と同じ内容ですが、以前ブログの記事にもしたhexpressのPHP版についてLTをしました。

さいごに

来年のことを言うと鬼が笑うといいますので、また来れるように仕事頑張ろう!でとどめておきます。

PHPカンファレンス北海道2016に参加してLTをしました

2016/4/16 に行われたPHPカンファレンス北海道2016に参加してきました。

スポンサーブースに展示してあった白い恋人タワー

はじめての飛行機での北海道

今回で4回目の北海道なのですが、これまで全部フェリーに自家用車を載せて行っていたので、若干不安もあったのですが、なぜか@koyhogeさんと偶然日暮里の駅で出会い、同じ飛行機ということで何事もなく札幌駅までたどり着きました。 幸先の良い始まりです。 成田空港出発前に搭乗口から

ホテルは車で旅をしたときにも使ったことがあるアパホテル〈TKP札幌駅前〉。本当はドーミーインにしたかったのですが、満室でした。どちらも朝食が豪華なのがウリで、朝からいくら丼を堪能できます。

ホテルに到着後、翌日のカンファレンスのLTスライドを調整して完成させてから、前夜祭のニラタワーもとい石鍋亭へ行きました。 ところが陽が落ちた街は極寒の地(気温3℃)で、カバンに入れた防寒着が役立ちます。この次期の北海道はまだ桜も咲く前で、まだ寒い日も多く注意が必要です。

石鍋の後は、まっすぐホテルへ戻って明日に備えました。

PHPカンファレンス北海道2016

ホテルでの朝食

会場の「札幌市産業振興センター」はとなりにイオンMaxValueがある、広い敷地にある建物です。 手前には積まれたままの残雪があります。雪じゃなくて良かった…

イベントは2トラック+スポンサーブースで、どのセッションも聞きたかったのですが、主にメイン会場にいました。

  • Prophecyを使ったユニットテスト
  • PHP7ブートキャンプ
  • PHPer人生、一度はフレームワークを作っておこう!
  • フロントエンドエンジニアのための軽量フレームワーク Lumen
  • PHPerに知ってほしいRDBの事
  • ウェブデザイナーでも覚えておきたいPHPのあれやこれや
  • 『例えば、PHPを避ける』以降PHPはどれだけ安全になったか
  • LT

スピーカーは地元北海道から南は九州博多からと、全国からすばらしいスピーカーの皆様が集まって、とても充実した一日となりました。 盛り上がりは、以下のまとめサイトを参照していただければと思います。

ランチのスープカレー(40辛)。あんまり辛くなかったので50辛にしておけば良かった。

イベントの後は懇親会、二次会、ラーメン、Barの順に巡りホテルに戻りました。

東京に…帰れるのか?!

日曜日は関東地方が大荒れの天気で、午前中から東京方面に戻る参加者から「飛行機飛ばない」「目的地変更かも」という悲鳴が聞こえてきました。 私は19:20と遅いフライトだったこともあり、(天気予報的にも)大丈夫なんじゃないかなーと、あまり深く考えていなかったのですが…

さて、ホテルで朝食後大通りを観光しようと思ったものの、札幌は朝から雨で地下街をブラブラ。 お昼にはロケットニュースで最近北海道はハンバーガーがブームというのを見ていたので、そのうちの札幌にあるTACKを目指して移動。

TACKのモッツァレラチーズバーガー。道内ビーフ100%の美味しいハンバーガー。ロケニューにも写真がないがマスターはかなり大きめのリーゼントだった

このあと「サッポロビール博物館 | 工場見学とミュージアム | サッポロビール」に行こうと思ったら「水曜日まで休館」という事実が@hamacoから伝えられ、しかたなくまた地下街をブラブラ(w)。三越のデパ地下でおみやげ買ったり、地下街の休憩スペースでPC広げてコード書いたり、北海道を満喫?!してました。 その間にも東京へ戻る飛行機の悲報が続き、これはやばいなーと思って少し早めに新千歳空港へ。

その時点でもう離陸しているはずの @koyhoge さんがまだ空港でTweetしているので、次の便の私は1時間半遅れだなーと思いながら空港でブラブラ。 とりあえず荷物をコインロッカーに入れて、立ち食い寿司の五十七番寿しで夕食を。

結局8つぐらいと日本酒を堪能

結局19:20分予定の飛行機は20:20に離陸し、混雑の成田に着陸した頃には終電(京成特急)の時間がギリギリ。若干電車が遅れていたので無事間に合って日付が変わった0:30頃帰宅。疲れたは半端なかったのですが、充実した3日間でした。

今後はもう少し早めのフライトにした方がいろいろドキドキしなくて良いなと。 実際、成田で朝まで?とか、翌日仕事どうしようかなーとか、考えていました。

LTしました

以前ブログの記事にもしたhexpressのPHP版についてLTをしました。

スライド公開して翌日には、はてぶのホットエントリに入るなど、盛り上がりをみせてくれたので、とても嬉しかったです。

さいごに

PHPカンファレンス北海道は4年ぶりの開催ということで、前回行けなかったリベンジをはたしました。 スタッフのイベント進行がスムーズで、参加者としてとても楽しめる1日でした。いろんな気付きもたくさん得て今後に活かせそうです。

今年は福岡も大阪も参加できる見込みなので、皆様再開しましたらイベントを一緒に楽しみましょう(もちろんビールもイベントに含まれますw)。

ステキなストラップとイベントステッカーを。ブログを書く前に茅場町Co-Edoにて。

PHPカンファレンス2015で発表しました

2015/10/03 に行われたPHPカンファレンス2015で発表をしてきました。

スライドは以下の内容です。

PHPカンファレンスでは公募セッションは最大30分のため、すべてのページについて話すことができませんした。

セッションはじまるときにComposerの利用状況についてヒアリングしたところ、半数以上の方が「これからComposerを使う人」だったため、 入門部分を中心に解説しました。

このブログでは、スライドの共有と共に、話せなかった部分ついて(とうまくいかなかったデモも)書いておきたいと思います。

Composerと、その歴史

PHPで開発をするのに、デファクトスタンダードになったといって良いComposer。

Composerは2012年3月1日に生まれました。最初のリリース番号は1.0.0のアルファ1です。 現在も1.0-devというバージョンで日々アップデートが行われています。 2012年というのはすごい最近ですよね。たった3年前です。ではその前はどうだったのか?少しふりかえってみたいと思います。

Composerの前はどうだったのか?

PHPにはじめて拡張モジュールやライブラリの置き場所ができたのは1999年、pearという名前でした。 perlのCPANに影響を受けていて、あくまでコードリポジトリという位置づけでした。 ComposerがDependency 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といったものに影響を受けていて、プロジェクト単位で依存関係を管理します。

Composerが必須になる流れ

さてpearを使っていた中で、一番インストールしたことがあるパッケージといえば何でしたか? 私はどんなプロジェクトでも必ず必要だったのはPHPUnitではないかと思います。PHPUnitインストールしたことがありますか? pearでやるとかなり面倒なんですよね、複数バージョン入れ分けなくてはいけないなんて事はなかったですか?(地獄でしたよねw)

昨年、PHPUnitはPEARから卒業しました。スライドではそのときのSebastionBergmannのツイートを引用しました。 つい最近サルベージしたので、アイコンは当時写真だったと思うのですが、今はイラストですね(良く似ていますww)。

具体的には、csvから始まって、pearに移って、2009年にはgithubに移って、今日ではpearから卒業する、長らくありがとうという内容です。 PHPUnit3.7.0からComposrで取得可能です。

Composerより昔のやり方

例えばPHPUnitを例にとって、Composerより前はどんな方法だったか思い出してみましょう。 スライドではPHPUnitのpearを使った導入方法を掲載しました。1つ1つはもう気にしなくて良いのですが、長いですよね。 たいてい秘伝のレシピにしているか、ググってコピペするか、会社でドキュメント化しているか、そんなところだったと思います。

秘伝のレシピの場合、もちろんコマンド1つかもしれないですが、初めてプロジェクトに入った人がわかるわけではないですね。 複数バージョンを同居させるとかになると、pyrus使ったりしてもう少し違う感じにはなるかと思います。 あと、iniのインクルードパスを設定しないとファイルが読み込めなかったですよね

Composerになった(今どきの)やり方

Composerになって、初めて入れるときはrequire、他の人はinstallコマンドを実行するだけで良くなりました。 なんて簡単なんだろう、環境設定マニュアルとか必要ないレベルですよね。 composer使ったことあるひとなら、git cloneしたリポジトリにcomposer.jsonがある段階でinstallを実行するはずです。 (phpunitはrequire –devじゃないとか?いうのはそのとおりですが、今回は省略しています)

PHPで正しく開発するには

今日ではこのようにPHPでもモダンな開発をするベースが整っています。 PHPではPHP The Right Wayというページに、そのすべてがまとまっています。 もちろんComposerについても書いてあります。 PHP The Right Way は PHPerが幸せになる為の道しるべを示してくれています。 もちろん各国の有志によって翻訳されているので、すぐ読めます。かならず読んでみてください。

スライドの高速道路出口は 高速道路風標識ジェネレーター を使ってみたかっただけで、深い意味はありません。

オートローディング

PHP The Right Wayではコーディングスタイルや名前空間といったことにも言及しています。 どちらにもPSR-4という記述がありますが、PSR-4はオートロードについての標準です。現在はPSR-0を含んでいるので、PSR-0でなくPSR-4を参照するのが良いでしょう。

オートロードとComposerの関係について

PHPでクラスをオートロードするには、_autoloadを実装して、クラスが見つからないときに指示してあげるか、splautoload_registerで予めクラスのパスを登録しておくという2通りのやり方があります。

「ちなみにこの方法でオートロードを実装したことがある人はいますか?」という問いにはどなたも手があがりませんでした。これはそのとおりだと思います。Composer以前ではほぼ気にする人はいなかったでしょう。

もしフレームワークを使ってアプリケーションを実装している人は、フレームワークがオートロードの仕組みを用意してくれていたりするので、より意識しないかなと思います。

デモ

本番ではうまくいかなかったのですが、こちらで解説します。(カンファレンスあるあるですね)

インストール

スライドの内容を参考にcomposerをインストールします。 composerはプロジェクトのローカルでなく、パスの通っているところに配置してください。 Right Wayにも書いてあります。 Windowsを利用の方は公式ドキュメントを参照ください。

GitHubのリポジトリからソースコードを取得します。

git clone git@github.com:sizuhiko/phpcon2015_demo.git

プロジェクト情報の入力

まずcomposer initコマンドでプロジェクト情報を入力します。 requireやrequire-devは必要ないので、noを入力すれば大丈夫です。

インストールコマンドの実行

initコマンドを実行したら、composer installコマンドを実行します。最初は何もありません。 vendorディレクトリが生成されるはずです。

実行してみる

php -S localhost:8000 src/router.php というコマンドを実行します。 ブラウザからサンプルページを実行してください。

Welcome to PHP と表示されるはずです。

次にSay\Helloクラスを実行してみます。/helloにアクセスします。

Fatal error: Class 'Say\Hello' not found in /phpcon2015_demo/src/router.php on line 19

というエラーが表示されるはずです。 ソースコードでは以下のように指定していますが、オートロードが定義されていないのでクラスは見つかりません。

use Say\Hello;

そこで、composer.jsonを編集して、以下のようにrequireの下に追記します。

    "require": {},
    "autoload": {
        "psr-4": {
            "Say\\": "src/Say"
        }
    }

変更を保存したら、composer dumpautoload というコマンドを実行します。

再度Say\Helloクラスを実行してみます。/helloにアクセスします。 すると、ブラウザに

Hello

と表示されるはずです。 今度は/emojiにアクセスします。 先ほどと同じようなエラーが表示されるので、composer.jsonを編集します。

    "autoload": {
        "psr-4": {
            "Say\\": "src/Say",
            "Write\\": "src/Write"
        }
    }

変更を保存したら、composer dumpautoload というコマンドを実行します。

再度Write/Emojiクラスを実行してみます。/emojiにアクセスします。 すると、ブラウザに

(^o^)

と表示されるはずです。

このようにオートロードについて自分で記述しなくても、名前空間の宣言をcomposer.jsonでおこなうと自動的にクラスをロードしてくれるようになります。

More Tips

この先は解説できなかった部分なので補足します。

リポジトリ管理

これについては第94回 PHP勉強会@東京〜PHPカンファレンス2015開催直前スペシャル〜で話しました。スタジオアルカナのレポートに詳しいログが残っていますので、そちらを参照ください。

スクリプト

Composerの強力な機能にスクリプト(フック)の実行があります。 installupdateなどcomposerのコマンド実行前と実行後に、スクリプトを実行できます。

  • pre-install-cmd
  • post-install-cmd

のようなイベント名です。 実行できるスクリプトは通常のCLIとPHPのクラスです。

例えば composer.json で以下のように記述します。

    "post-install-cmd": [
        "MyVendor\\MyClass::warmCache",
        "phpunit -c app/"
    ],

より詳しい情報は公式サイトを参照して欲しいのですが、これの使い方は2つ考えられます。

1つ目は、すでに存在するライブラリに対するプロキシとしたい場合です。 公開されているライブラリをForkしたり、コピーしてくることなく、独自の変更を加えたい場合や、ライブラリをインストールした後で独自のconfigを追加したい場合など、社内で複数のプロジェクトにまたがって同じカスタマイズをしたい場合は有効です。それぞれのプロジェクトではプロキシしたcomposer.jsonのあるリポジトリを指定するだけで、元のライブラリを修正することなく、同じようにカスタマイズ状態を利用できます。

2つ目は、フレームワークやライブラリを作った場合です。現在多くのフレームワークはアプリケーションテンプレートとして、composer create-projectに対応したスケルトンを用意しています。何もなければそれを取得すれば良いのですが、もちろんcreate-projectコマンドにもフックポイントが用意されているので、install後には環境設定ファイルなどがコピーされるようになっています。

まとめ

このようにComposerはpearでできていたパッケージ(コードリポジトリ)管理から、より多くの機能を持って、現在のアプリケーション開発になくてはならないものとなっています。

このセッションでComposerを使うようになってくれる人が増えることを期待してまとめとしたいと思います。

おまけ

LTのスライドも公開します。

複雑な正規表現を簡単に作れるようにした

この記事は先日の正規表現を簡単に作るにはの続編になります。

前回、RFC3986のような複雑な正規表現をVerbal Expressionの既存実装でやろうとすると、うまくできないという問題に直面しました。 そこでRubyで実装されていたHEXPRESSをPHPへ移植しようという流れです。

PHP版Hexpressを作った

さっそく移植してみました。

hexpress

PSR-2の対応が実施中なのですが、Ruby側の機能とテストはすべて移植し、PHP版でいくつか機能追加をしています。

どんな感じか

READMEに書いてあるとおりインストールはcomposer経由でできます。

composer require sizuhiko/hexpress

具体的な利用方法は以下のサンプルのとおりです。

use Hexpress\Hexpress;

$pattern = (new Hexpress())
    ->start("http")
    ->maybe("s")
    ->with("://")
    ->maybe(function($hex) { $hex->words()->with("."); })
    ->find(function($hex) { $hex->matching(function($hex) {$hex->word()->with("-");})->many(); })
    ->has(".")
    ->either(["com", "org"])
    ->maybe("/")
    ->ending();

echo $pattern;             #=> "^https?\:\/\/(?:(?:\w)+\.)?([\w\-]+)\.(?:com|org)\/?$"
echo $pattern->toRegExp(); #=> "/^https?\:\/\/(?:(?:\w)+\.)?([\w\-]+)\.(?:com|org)\/?$/"

Hexpressクラスのインスタンスを生成して、メソッドチェインで正規表現を組み立てます。 ネストしたい場合は、コールバック関数を指定すると、新しいHexpressのインスタンスがパラメータで渡ってくるので、 それに対してメソッドチェインでつないていきます。

Hexpress__toString()を実装しており、文字列表現を取得すると指定された定義を展開します。 実際に正規表現として利用するにはtoRegExp()を呼び出すと、左右にデリミタを挿入した文字列が取得できるので、preg_matchなどの関数で利用可能になります。 例えば以下のような利用方法です。

preg_match("http://example.com/", $pattern->toRegExp());

複雑な正規表現は定義できたのか?

できました!!

テストコードとしてRFC3986Test.phpを作成しました。 実装は結構長いので、こちらに添付することは省略しますが、RFCの定義に書いてあるとおりそのままメソッドをつないでいくだけで、 RFCに対応した正規表現を構築することができました。(※IPv6の定義は未実装です、ご了承ください)

PHPUnitのデータプロバイダexampleUriProviderでマッチさせるパターンをftp,www,mail,news,tel,telnet,urnについて定義してすべて通過しています。

PHP版では、マッチするときfindメソッドで名前付きサブパターンを利用できるようにしました。 以下の例のように、findの第二引数にportを指定できます。

    private function port()
    {
        return (new Hexpress())->has(':')->find(function ($hex) { $hex->digits(); }, 'port');
    }

上記を含むパターンをpreg_matchで処理すると、マッチング結果に名前付きで値を取得できるようになります。

preg_match("http://example.com:80/", $pattern->toRegExp(), $matches);
echo $matches['port'];   #=> '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という正規表現を簡単に組むことができる仕組みがあります。

http://verbalexpressions.github.io/

サイトに「Regular Expressions made easy」と書いてあるように、簡単に正規表現が作れることを表明しています。 様々な言語にポートされていますが、もちろんPHP版もあります。

https://github.com/VerbalExpressions/PHPVerbalExpressions

サイトのサンプルにも書いてあるとおり、以下のようなURLにマッチする正規表現が記述できます。

use VerbalExpressions\PHPVerbalExpressions\VerbalExpressions;

$regex = new VerbalExpressions;
$regex  ->startOfLine()
        ->then("http")
        ->maybe("s")
        ->then("://")
        ->maybe("www.")
        ->anythingBut(" ")
        ->endOfLine();

echo $regex->getRegex() ."\n";
if (preg_match($regex, 'http://github.com')) {
    echo "valid url\n";
} else {
    echo "invalud url\n";
}

1つ目のechoの結果は /^(?:http)(?:s)?(?:\:\/\/)(?:www\.)?(?:[^ ]*)$/m で、2つ目のechoは valid url を表示します。 VerbalExpressionsクラスに toString メソッドが実装されているので、 preg_match 関数でそのまま使えます。

複雑なことはできるか?

例えばRFC3986に書いてあるURLパターンをマッチさせようとすると、どうなるでしょうか? 一旦スキーマ部分だけ記述してみます。

$rfc3986 = new VerbalExpressions;
// scheme
$scheme = new VerbalExpressions;
$scheme->add("http")->maybe("s")->_or("ftp");

$rfc3986->startOfLine()
        ->add($scheme)
        ->add("://");
echo $rfc3986->getRegex() ."\n";

結果は /^(?:\(\?\:http\)\(\?\:s\)\?\)\|\(\?\:ftp)(?:\:\/\/)/m のようになってしまい、期待通りではありません。 この実装は入れ子には対応していないようです。

もう1つのVerbalExpression実装

PHPにはもう1つ別のVerbalExpression実装があります。

https://github.com/markwilson/VerbalExpressionsPhp

こちらの実装はREADMEに入れ子について記述されているように、入れ子の対応はされているようです。 では早速RFC3986の定義を試してみましょう。

$rfc3986 = new VerbalExpression;
// scheme
$scheme = new VerbalExpression;
$scheme->then("http", false)->maybe("s", false)->orPipe("ftp", false);

$rfc3986->startOfLine()
        ->find($scheme)
        ->find("://")
        ->endOfLine();
echo $rfc3986->compile() ."\n";

結果は ^((?:http)(?:s)?()|()(ftp))(\:\/\/)$ のようになってしまい、まぁ不正ではないのですが、かなり無駄があります。

現時点結局のところ

どちらの実装も簡単なパターンをやるときには良いのですが、ちょっと複雑なパターンを実装しようと思うと微妙です。 大体、簡単なパターンはそのまま正規表現書けば良いじゃん… という話ですしね。

目指したいところ

RubyのVerbalExpressions実装には HEXPRESS があります。 これはVerbalExpressionsよりさらに便利なヘルパーを備えて Human Expressions, a human way to define regular expressions という標語のとおりより簡単に実装できるように見えます。

これをPHPに移植して使えるようにしようというのが、直近やろうとしていることです。

さいごに

日本PHPカンファレンス2015が10/3(土)に行われます。 私もスピーカーとして登壇しますので、もしご都合がつく方はよろしくお願いします。