Technote

by sizuhiko

PHPカンファレンス関西2012に参加しました

<!– more –>PHPカンファレンス関西2012のため、5/11夕方から5/13昼頃まで大阪へ出かけていました。

今年は2トラックで興味深いセッションが多く、とても楽しめました。スタッフの皆様、スポンサー、並びに忍びの方々 ありがとうございます。

前夜祭では噂の無限もやしを食べられた(※1)し、懇親会や2次会、3次会ではかなり濃い技術ネタにあふれていてとても楽しかったです。あぁ、こう書くと飲みに行ったみたいに見えちゃいますね….(半分は事実ですが)

イベントでは「BDDで行こう」というLTが無事当選し、発表してきました。資料はこちら(TwileShare)です。タイミング良くこれから私が作成したCakeBehatの紹介が始まる、というところで銅鑼が鳴りまして、まぁ発表者的には美味しい流れでした www

きっかけは作れた(※2)ので、続きはWebで(GitHub) ということですね。スライドの内容とGitHubのREADMEを併せてみてもらえれば、CakeBehatが何をしているのかわかると思います。
とはいえまずはBehatを使ってもらって、その後でCakePHP使っている人はぜひ、という流れです。

それと懇親会LTが行われるということで、本編LTでも発表するので空気を読んで自重していたのですが、追加枠が出たということで14:30ぐらいの段階で申し込みました。懇親会まで3時間ぐらい、その間に本編LTもある中でスライド(TwileShare)を作成しました。内容はBlogで公開しているQueryPathの紹介と、GitHubで公開しているQPPHPのREADMEを合体したものです。これまでにLTをやったことない人でも、このように既出のBlog記事などから資料を作れば簡単にできると思います。@koyhogeさんの懇親会LTでも出てきたのですが、5分なので何があってもノリで切り抜けられる場合がほとんどです。見慣れた顔ぶれだけじゃなくて、新鮮なネタも応募してもらえるといいなぁと思います。

LTで発表したCakeBehatQPPHPについて、興味をもたれてわからないことがあれば、GitHubのissueなどでご連絡いただければと思います。

また来年のPHPカンファレンス関西が楽しみです。

それでは皆様、PHPカンファレンス(東京)とPHPMatsuri(福岡)でお会いしましょう!!

※1: もちろん有限になる場合があります。翌日3次会で行ったら終わっていたのです。。。

※2: 5分ではすべて紹介できないので、面白そうと思ってもらえたところで時間(銅鑼)になることで、Webサイトを訪問してもらえる&誤解を招かなくていいかなぁと思っていたりします。

QueryPathを使ってHTMLを操作する

<!– more –>昨年末phpQueryについて、これはいいね!と取り上げたのですが、その時点でも若干更新が止まっていたり、XHTMLの解釈が微妙だったりとかいくつか不安要因があったのですが、そんな不安を解消するjQueryインターフェースを実装したライブラリを発見しました。

それがQueryPathです。

QueryPathが当たり前に良いと思う点

  • 日本語が普通に使える
  • XHTMLが普通に使える
  • 更新されている
  • 拡張(extension)が書きやすい
  • テストコードがある
  • jQueryインターフェースがほぼ忠実に再現されている

こういう当たり前にできて欲しい事が、意外と日本語環境だとうまくできなかったりするのですが、特に意識することなくできるのは良いと思います。 もちろんmetaの文字コード指定など、ある程度ちゃんとHTMLが書かれている事は重要です。

QueryPathが独特と思う点

QueryPathは標準で5つの拡張機能(extension)を持っています。

  • QPDB : データベースへのアクセスと、検索結果をテンプレートへの差し込むことができるようになる
  • QPList:配列で渡した内容をtableタグやul、olなどに展開してHTML化できる
  • QPTPL:連想配列のキーをidやclassなどのクエリ情報と解釈して、テンプレート流し込み機能を提供する
  • QPXML:XMLを操作する拡張機能
  • QPXSL:XSLTを利用する拡張機能

独特というのは、拡張機能が簡単に実装できるので、拡張を使えばこんな事、あんな事、jQueryプラグインを書くかのように自由にできますよ、という部分に集約されると思います。

使ってみよう

インストール

QueryPathは3つの導入方法に対応しています。

  • PEARパッケージ
  • pharファイル
  • Composer

ここではpharファイルをダウンロードして始めてみます。pharファイル以外の導入方法はGitHubの公式ページを参照してください。

ダウンロードページより QueryPath-version.pharというファイルをダウンロードします。この記事時点での最新versionは2.1.2です。ダウンロードしたファイルの名前をQueryPath.pharにリネームしておきます。

サンプルHTMLの取得

前回のphpQueryと同じく、WORDPRESSの日本語TOPページのHTMLを使ってみたいと思います。

wget http://ja.wordpress.org/

phpshを使って試す

こちらも前回と同様に、簡単に試すにはインタラクティブシェルを使うのが便利なので、phpshを使います。

bash-3.2$ phpsh
Starting php
type 'h' or 'help' to see instructions & feature

php> require 'QueryPath.phar';

php> $html = htmlqp('index.html');

php> = $html->find('#blog .post .entry')->eq(0)->text()
"ntttttttttWordPress 3.3.2 が利用できるようになりました。これはすべての前バージョンへのセキュリティアップデートです。nWordPress に含まれる3つの外部ライブラリでセキュリティアップデートがありました:n    Plupload (バージョン 1.5.4)、WordPress ではメディアのアップロードに使用しています。n    SWFUpload、WordPress では以前にメディアのアップロードに使用していました。おそらくプラグインによってはまだ使われています。n    SWFObject、WordPress では以前に Flash コンテンツの埋め込みに使用していました。おそらくプラグインやテーマによってはまだ使われています。ntttttttt"

ブログエントリーの先頭記事を抜き出してみました。phpQueryは配列キーにセレクタを記述する方式だったのですが、QueryPathではPHP言語としての「->」の部分以外はjQueryと同じだとわかるでしょう。 またQueryPathにはqpというコア関数もあるのですが、こちらはXML用で、HTMLを利用する場合はhtmlqpを使っておいた方が良さそうです。

最後に

php> = $html->top()->html();

を実行すると、HTML全文を文字列として取得することができます。日本語がまったく問題ないことを確認できると思います。

※ $html->top()->innerXHTML(); ではなく、html関数でないと htmlタグとか含まれないので修正しました。(5/7)

まとめ

現時点でもHTMLの取得にはURL指定、ファイル指定など様々な対応がされており、DB連携やテンプレート機能などそのままでも結構つかえるんじゃないかと思っています。

ただ毎度DOM操作するの?とかいう部分もあるとは思うので、phpQueryっぽいPHP構文が含まれたPHPファイルを出力できるような拡張を作ってみたいなと思っています。まずは素のPHP部分から、その後でCakePHPとの連携も含んでみたいなぁという計画です。拡張名は標準のものを参考にするとQPPHP?なのかな。Pが続くと見づらいなぁ。名前は大事なので何か考えないと。。。

phpQueryを使ってデザイナーとプログラマーを完全分業できるようにする(導入編)

<!– more –>これまで多くのテンプレートエンジンが登場してきましたが、HTMLに全く手を入れないでデザイナーとプログラマーが分業することは困難でした。 もちろんSmartyのテンプレートが編集できる人がいたり、PHPTALのようにほとんどHTMLには手をつけない方法があったりと、これまでの方法でも分業することは可能だと思います。

ただHTMLには多少の手を入れなくてはいけない、そういう意味でKwartzのようにプレゼンテーションロジックを分割できるテンプレートシステムはとても良いと思っています。ただセレクターがCSS3セレクターでないのが難点かなぁと思っています。

そこで目を付けたのがphpQueryという、名前からして思い当たるjQueryのセレクター機能を搭載したPHP実装になっています。

phpQueryは内部的にPHPのDOMDocumentを使っていて、エレメントを探し出すのに便利なセレクター記法を持っています。

今回はphpQueryを使って静的HTMLの一部をPHPコードに書き換えるという導入をやってみます。

本当は時間があればViewコンポーネントまで作って、githubに展開したかったのですが、これは2012年早々の目標になる予定です。

phpQueryの取得

phpQueryは

  1. pear
  2. google-code
  3. github

のいずれかから導入可能です。この記事ではgithubから取得して進めます。

git clone git://github.com/bluelovers/phpQuery.git

サンプルHTMLの取得

この記事では、みんな大好きWORDPRESSの日本語TOPページのHTMLを使ってみたいと思います。

mkdir templates
wget http://ja.wordpress.org/
mv index.html templates

ここで注意なのですが、現在DOMDocumentではXHTMLを正しくパースできないようです。そこで、通常のHTMLとして解釈できるように先頭数行を以下のように書き換えます。

<html>
    <head>

DOCTYPEを削除し、htmlとheadにあった属性を削除しています。

ただXHTMLでなくHTML記法で書かれたページは問題ないので、この課題についてはあまり深入りせず先に進む事にします。

ただDOCTYPEや属性は、後で追加できるのでViewクラスにしたときに何かサポートできるようにしたいなぁと思っています。

の赤枠で囲った部分に関して、PHPの動的コードに変換してみましょう。

phpshを使って試す

簡単に試すにはインタラクティブシェルを使うのが便利なので、今回もphpshを使います。

bash-3.2$ phpsh
Starting php
type 'h' or 'help' to see instructions & features

php> require('phpQuery/phpQuery/phpQuery.php');
php> $file = file_get_contents('template/index.html');
php> $html = phpQuery::newDocumentHTML($file);
php> echo $html->html();

最後のhtml()で読み込んだHTMLがそのまま出力されることを確認しましょう。

ブログ記事の箇所のHTMLは以下のようになっています。

<div id="blog" class="section">
  <div class="main">
    <h3>ブログ</h3>
    <div class="post" id="post-2057">
    <h4><a href="http://ja.wordpress.org/2011/12/13/wordpress-3-3-ja/" rel="bookmark" title="WordPress 3.3 日本語版リリースのお知らせ へのパーマリンク">WordPress 3.3 日本語版リリースのお知らせ</a></h4>
    <h6>2011年12月13日</h6>
    <div class="entry">
      <p>WordPress 3.3 日本語版をリリースしました。</p>
    </div>
  </div>
  <div class="post" id="post-2042">
    <h4><a href="http://ja.wordpress.org/2011/12/13/wordpress-3-3-sonny/" rel="bookmark" title="WordPress 3.3「Sonny」 へのパーマリンク">WordPress 3.3「Sonny」</a></h4>
    <h6>2011年12月13日</h6>
    <div class="entry">
      <p>WordPress 3.3「Sonny」がご利用いただけるようになりました。</p>
    </div>
  </div>

ブログ記事は $posts という配列に入っていると仮定します。

php> $html['#blog .post:gt(0)']->remove();
php> $html['#blog .post']->wrapPHP('foreach($posts as $post) {', '}');
php> $html['#blog .post']->attrPHP('id', 'echo "post-$post->id;"');
php> $html['#blog .post h4 a']->attrPHP('href', 'echo $post->url;')->attrPHP('title', 'echo $post->title;')->php('echo $post->title;');
php> $html['#blog .post h6']->php('echo $post->date;');
php> $html['#blog .post .entry p']->php('echo $post->intro;');

php> print $html->php();                                                                                             

のようにphpshで実行すると、先ほどのHTML部分が以下のようになります。

<div id="blog" class="section">
  <div class="main">
    <h3>ブログ</h3>
    <?php  foreach($posts as $post) {  ?>
      <div class="post" id='<?php  echo "post-$post->id";  ?>'>
        <h4><a href="<?php  echo $post->url;  ?>" rel="bookmark" title="<?php  echo $post->title;  ?>"><?php  echo $post->title;  ?></a></h4>
        <h6><?php  echo $post->date;  ?></h6>
        <div class="entry">
          <p><?php  echo $post->intro;  ?></p>
        </div>
      </div>
    <?php  }  ?>
  </div>

どうです?

jQueryで見慣れたセレクタ記述と、少しのphpQueryの拡張記述で、HTMLを直接変更することなくPHPコードを含んだテンプレートファイルに変換することができました。

phpQueryが用意しているjQueryポートしたセレクタや、PHPコードを出力する拡張関数は、google-codeの公式ページを参照するとわかります。

さいごに

最初にHTMLファイルを読み込む部分や、最後にphp()関数を使ってPHPを含むコードに変換する部分をモジュール化して、各フレームワーク向けのViewコンポーネントとして提供したいなぁと思っています。

ただ普段使っているのがCakePHPばかりなので、他のフレームワークについてわかる人に協力してもらえたらなぁと思っています。

またViewコンポーネントにする際はQueryTemplatesというphpQueryを拡張したコードも使おうかなぁと思っています。

CakeBehat の master を CakePHP2.0 対応に切り替えました。Seleniumによるテストも簡単に。

CakeBehat for CakePHP2.0

PHPMatsuri 2011 で完了させた CakePHP2.0 対応ですが、しばらく 2.0 ブランチで開発バージョンとして扱っていたものを最新のCakePHP,Behat,Minkで動作確認してmasterに昇格させました。

https://github.com/sizuhiko/CakeBehat

はじめに

CakeBehatはCakePHPからBehatを呼び出してテストするためのプラグインです。CakePHP1.3対応として公開したのが2011年6月投稿です。

http://my.opera.com/sizuhiko/blog/2011/06/20/cakephp-behat

インストール

前提事項

  1. gitが利用可能なこと
  2. PHPUnitがインストールされていること
  3. CakePHP2.0.xがインストールされていること
  4. MySQLなどデータベースがインストールされていて、テスト用データベースが準備されていること

導入

CakePHPのルートディレクトリへ移動して、以下のコマンドを実行してください。

cd plugins
git clone git@github.com:sizuhiko/CakeBehat.git
cd ..

すると、plugins 配下に CakeBehat のディレクトリができているはずです。CakeBehatプラグインを有効にするためにbootstrapでプラグインの読み込みを行います。

app/Config/bootstrap.phpの最後に追加します。
....

CakePlugin::load('CakeBehat');

次に、CakeBehatで必要なBehatやMinkをダウンロードし、featues を初期化します。CakePHPのルートディレクトリに移動して、以下のコマンドを実行します。

lib/Cake/Console/cake CakeBehat.init

するとCakePHPのルートディレクトリに featues ディレクトリができているはずです。 その他にplugins/CakeBehat/Console/Command の下に behat.phar と mink.phar がダウンロードされます。

環境設定

Behat/Mink環境設定

app/Config/behat.yml がinitコマンドによって生成されています。

5行目に

base_url: http://test.localhost:8888/application-name/

という設定があります。これはアプリケーションのルートパスを設定するもので、ホスト名、ポート番号、アプリケーション名などを指定します。ホスト名はできるだけtest環境と識別可能なものにしておく事がオススメです。

実行する

基本的な環境設定は、ここまでで、behatは実行可能な状況になっています。 具体的にサンプルアプリケーションのコードを使っての解説は、以前のPostと同じなので、以下のURLから確認してください。

http://my.opera.com/sizuhiko/blog/2011/06/20/cakephp-behat

ただし実行コマンドがプラグイン化に伴って変更されています。プラグイン名が付いたので、cake behat というシンプルなものからは少し遠くなってしまいましたが、以下のコマンドを実行してください。

lib/Cake/Console/cake CakeBehat.bdd

Ajaxを利用したページをテストしたい

最新版のMinkでは、Ajaxを使ったページをテストできるように、ブラウザエンジンを選択することができるようになっています。

  1. GoutteDriver : Ajaxは使えないがライトなブラウザテストが可能
  2. SahiDriver:ブラウザのプロキシ設定が必要だが、様々なブラウザでテストが可能
  3. ZombieDriver:Node.js を使ったブラウザテストが可能
  4. SeleniumDriver:Mink1.2 からサポートされた、お馴染みのSeleniumによるテストが可能

公式のBehatやMinkのドキュメントを参照すると、Seleniumなどを使う場合の方法が書いていませんコードを書いて初期化しないといけませんが、Behat+Minkのインテグレーションでは、behat.ymlに設定するだけで簡単にSeleniumによるテストが実行できるようになります。

JavaScriptセッションエンジンを指定する

CakeBehatではデフォルトのJavaScriptセッションエンジンをSeleniumとしています。app/Config/behat.yml の 4行目に

javascript_session:   selenium

設定を入れてあります。まだ試していませんが、sahiやzombieを使う場合はこの設定を変更すれば動作するはずです。

JavaScriptを使ったページをテストしたいシナリオでは

@javascript アノテーションをfeatureに指定します。

サンプルアプリケーション(blogチュートリアル)のindex.ctpでDeleteボタンがクリックされたときにtrエレメントを消すだけの実装を追加してみました。app/View/Posts/index.ctp

<td><a href="javascript:void(0);" onclick="$(this).closest('tr').remove();">Delete<?php echo $index++; ?></a>

のようにしました。

このリンク「Delete3」をクリックして3行目を削除するfeatureを書きます。

  @javascript
  シナリオ: 記事を削除できること
    前提 "トップページ" を表示している
    かつ "Title strikes back" と表示されていること
    もし "Delete3" のリンク先へ移動する
    ならば "Title strikes back" と表示されていないこと

「リンクをクリックする」みたいなステップへ書き換えた方が本当は直感的なのですが、とりあえず「リンク先へ移動する」を使っています。

後は、Seleniumを実行しておくだけです。

java -jar selenium-server-standalone-2.14.0.jar 

これだけです。特にSeleniumを使うと意識しなくても、@javascriptを付けたシナリオだけでFirefoxが起動してテストが実行されます。もちろんこのJavaScriptを使ったテストも成功します。

さいごに

BehatやMinkは少しのバージョンアップ違いでうまく動かないケースがあります。もしCakeBehatを使ってうまく動作しないケースなどはgithubのissueなどに書き込んでいただければ、改善していきたいと思っていますのでよろしくお願いします。

PHPMatsuriで"できたこと"

<!– more –>DSC05649

大事なことは最初に

PHPMatsuri 2011は昨年に続き、多くの参加者に恵まれまして、無事終了することができました。今年は幹事的な立場で進めてきたのですが、大勢のスタッフやスポンサー、参加者の皆様に支えられたことを感謝しています。

人数もスタッフ、ゲスト、参加者合わせて目標としていた100名に近い96名と、ほぼ満員御礼で開催できたことがとても嬉しいです。

さて今回は、イベント開催前にリレーブログ「PHPMatsuriに参加するとできること」で書いた内容をふりかえる形で開催/参加報告にしたいと思います。

とにかく聴いてみる

DSC05620

初日は午前中から、夜の闇PHPMatsuriまでとても濃いセッションが展開されました。昨年は「ハッカソンで何かを作る」というよりは講演スペースで聴く人の割合が多かったのですが、今年は聴講中心という人の割合よりも、ワークショップとセッションへ交互に参加するという、より幅広くイベントを楽しむスタイルの人が多かったと思います。

夜には昨年はJIREIマスターか登場したのですが、今年は闇の者(NINJA)が登場し、会場を盛り上げていました。闇PHPMatsuriは当初プログラム計画にない持ち込み企画だったのですが、闇の皆様には大変感謝しています。海外のゲストもとても楽しんでいたと思います。

2日目の発表LT大会でも、昨年とほぼ同数の40名近くの参加者がPHPMatsuriでの体験を発表。このLTが中盤にさしかかった休憩時間には「今回イベントとか初参加なのですけど、LTを見て作ったものを発表してみたいな、と思うのですが(エントリーしていないけど)これから可能ですか?」という声をいただき、審査時間の間にリジェクトトーク時間を急遽作りました。これは昨年になかったサプライズで、スタッフのshin1x1さんや、多くの方が「まぁ発表しなくても良いかな?」から「発表したい」に変わっていく瞬間を見れたことはスタッフとして嬉しいことです。リジェクトトークの時間はおよそ30分ぐらいあったのですが、賞品がもらえる訳でもないこの時間に隙間無く発表者が飛び入り参加したのは、PHPMatsuriの中毒症状というか、始めてイベントに参加した人にとっても、これから他のイベントに参加するきっかけになったのではないかと思っています。

また通常のスポンサード以外にも、初日の15時ティータイムにスイーツの差し入れをしてくれた「わったい菜」のスイーツが絶品でした。

何か作ってみたい

初日の昼間の状況は前述したとおりですが、各フレームワークのワークショップも大変盛況でした。昨年は時間が近くなったら何となく集まってやっていたワークショップも、今年は「どこでやりますか?」「すぐ始まりますか?」など参加者の意欲がとても熱く、最初はスタッフもバタバタしてしまい申し訳なかったなぁと思いました。ワークショップに関して今年は特に熱かった(部屋の温度が暑かったのは参加者の熱気では?と思うぐらい)!

また、そこかしこでは、明日の発表に向けて黙々と作っている人などもいて、それぞれの祭りを楽しんでいる様子が伺えました。

それを証明するのが、増井さんと有志の方が定点カメラで撮影した深夜の様子。昨年はほとんどいなかった貫徹組が今年はとても多かったのがビックリでした。コアデベロッパーも質問が来るかもしれないからと、ずっと起きてくれていたのにも感謝です。

他の人と一緒に作ってみたい

残念ながらまだ他の人と一緒に作ってみて発表、というところまでは中々難しいですね。ただポジションペーパーに協力いただいたのは嬉しかったです。少しずつ、昨年よりも今年の盛り上がりが熱かったように、共同製作のようなことが来年以降あるのではないかと期待しています。

長い夜の過ごし方

DSC05675

今年の会場はとても広く、会場の外でも開発を続ける様子が見受けられました。隣のビジネスコーナーや、談話室、はたまたマッサージチェアでといった具合に自分に合った?!スタイルで開発をしていたのが印象的でした。

夜のテストワークショップに至っては時間を延長して4時間以上やっていたり、スポンサーセッションがあったり、闇の忍者が現れたりと。

その後深夜はアングリーバードのゲーム大会が行われていたり、例のEpic Saxが流れていたり、ともかく様々な楽しみ方で盛り上がっていました。

何でも良いので発表してみよう

DSC05804

そして多いに盛り上がったLT大会。あれほど接続テストをしたのに、いざ本番でうまく画面がでなかったり、緊張でタイマーを見てなくて一番大事なところで発表が終わったり(これは関東のLTでは一番盛り上がるネタ手法)、キモいw 発表があったりと、あっという間に3時間が過ぎたのではないかと思います。

もちろん前述したとおりリジェクトトークもあり、ビールタイムもありで、盛りだくさんではなかったかと。

後は今年もsioさんにドラ娘を任せっきりになってしまって、皆さんドラ娘も貴重な機会なので叩いてみるといいよ、と思うのですがなかなかに難しいですね。一度叩くとこれも中毒になるものなので、ぜひ来年はドラ娘に協力していただける方がいるといいなぁと思っています。

最後に

すでにここまでにも嬉しかった事などを書いたのですが、ちょっと書ききれなかったところでもあるので2つほど印象に残っていたことを紹介します。

  1. CakePHPで何か作ろうと思って参加したけど、Titanium が面白そうでそちらで作ったものを発表します、という発表があった。これはPHPMatsuriのようにセッションやワークショップがあった効果だと思っています。また参加者の人が通常仕事では出会う場面がなかったかもしれない、新たな発見をする機会でもあったのではないかと。
  2. CakePHPコアデベロッパーのグラハムが、昨年よりも多くの質問がきたり、声をかけてくれる人が増えたけど何かしたの?と驚いていた。これまでに公開されたblogの記事をいくつか読んで感じたのは、せっかくの機会なので交流を持とうと思ってくれていた人の多さでした。海外のコアデベロッパーに会うには、もちろん海外のカンファレンスに行くのが近道です。ただ参加費や言葉の問題などを考えると簡単ではありません。PHPMatsuriではそういった開発者にも交流の機会を作りたいという思いもあるので、それは今回とても参加者の熱意に感謝しているところであります。

PHPMatsuriは1月ぐらいから、少しずつ準備が始まり、3月の震災以降開催場所の検討やイベントの内容などオンラインで様々なスタッフ協議が行われてきました。来年のことを現時点で考えられないぐらい抜け殻になっている青年団がほとんどだと思いますが、コメントボードに書かれていた熱い想いを受け止めていければなぁと思います。

まぁ偶然とは言え、ハッカー賞、次点が某方面で出ましたので、そういう流れなのかもしれませんが、またお知らせができるときがくるまで、各地の勉強会・開発合宿・カンファレンスなどで盛り上がって行ければなぁと思っています。

本記事中の写真は@koyhogeさん、@suzukiさんのflickrよりお借りしています。

イベント全体の様子は、アルバムサイトを是非ご覧下さい。