PHPカンファレンス2010の発表資料
今年もPHPカンファレンスが開催されました。
今回はテックデイにてフレームワークアップデートLTでSymfonyのアップデートと、LTでは僕が執筆した書籍「パーフェクトPHP」の発表を行いました。
Symfony2
TwitterのTLみてたらSymfony2を使ってみたいと言ってくれる方が多くてよかったなーと思いました。Symfony2は実際に使ってみてすごくいいなと思っているので、今回多くの方々にSymfony2のことを知ってもらえてよかったなと思います。
Symfony2は何よりも高速で、柔軟で、拡張性が高く、すごくいいですよ。アルファ1がリリースされたあたりから、徐々にブログに情報まとめていきたいなと思っています。
発表上手だねと言ってくれる方がいてすごくうれしかったです。前日発表練習を軽くしつつ時間の調整を行っていたのですが、そのおかげかスムーズに進められたかなと思います。聞いていただいた多くの方々、本当にありがとうございました。
パーフェクトPHP
大型本を書いたのははじめてだったのですが、時間をかけて書いた本だけに、多くの方に「読みたい!」と言っていただけたことが本当にうれしく思います。また発売したらTwitterとかで連絡しますので、是非買ってください!
共著者のid:sotarok、id:gusagiにも本当に感謝。2人がいなければこの本はありませんでした。
現時点でほとんど書き終わっており、細かいチェックや本文以外の加筆など行っている段階です。発売日は11月上旬〜中旬を予定しています。値段ですが、たぶん3600円前後になると思います。
ちなみにLTの順番ですが、shuffle()関数を用いたスクリプトを書いてランダムで決めました。不正はありません!
実行委員として参加して
今回初めて実行委員として参加しました。色々反省点があるので、来年のために改善事項などをまとめています。ご要望などありましたら、なんでも結構ですので連絡いただければと思います。
実行委員や当日スタッフの方々、本当にお疲れ様でした。特に委員長のid:Yudoufuと、前回委員長のすずきさん。ご迷惑をたくさんおかけしてしまいましたが、本当に頼りになりました。ありがとうございました!
そして、スポンサーの方々、発表いただいた方々、ご来場いただいた多くの方々、皆さまのおかげで今年も無事PHPカンファレンスを行うことができました。これからもよろしくお願いいたします。
SimpleXMLで名前空間に属する要素を出力
<?xml version="1.0"?> <services xmlns:nequal="http://nequal.jp/schema"> <nequal:service id="openpear"> <nequal:name>Openpear</nequal:name> <nequal:uri>http://openpear.org/</nequal:uri> </nequal:service> <nequal:service id="deadlinetimer"> <nequal:name>DEADLINETIMER ジェネレーター</nequal:name> <nequal:uri>http://deadlinetimer.com/</nequal:uri> </nequal:service> </services>
こんな感じで名前空間に属した要素を出力したいんだけど、SimpleXMLでどうしたらいいのかよくわからないということで調べてみました。
とりあえずnameとuriプロパティを持つNequal\Serviceクラスがあるものとします。
<?php use Nequal\Service; // rootとなる要素に必ず名前空間を指定する $xml = new \SimpleXMLElement('<services xmlns:nequal="http://nequal.jp/schema"></services>'); $services = array( new Service('Openpear', 'http://openpear.org/'), new Service('DEADLINETIMER ジェネレーター', 'http://deadlinetimer.com/'), ); foreach ($services as $service) { // addChild()メソッドの第3引数に、同じ名前空間を指定する $element = $xml->addChild('service', null, 'http://nequal.jp/schema'); $element->addChild('name', $service->getName()); $element->addChild('uri', $service->getUri()); } echo $xml->asXML();
重要なのが、SimpleXMLElementのコンストラクタに渡すデータに名前空間を指定することと、そこに指定した名前空間の値をaddChild()の第3引数にも指定することです。名前空間に属している要素の中
に更に子要素を追加する場合はaddChild()メソッドに名前空間を指定しなくてもいいみたいです。名前空間を変えたい場合は当然指定する必要があります。
実行結果は以下。
<?xml version="1.0"?> <services xmlns:nequal="http://nequal.jp/schema"><nequal:service><nequal:name>Openpear</nequal:name><nequal:uri>http://openpear.org/</nequal:uri></nequal:service><nequal:service><nequal:name>DEADLINETIMER ジェネレーター</nequal:name><nequal:uri>http://deadlinetimer.com/</nequal:uri></nequal:service></services>
SimpleXMLElement::asXML()って整形されないんですよね。DOMDocumentなら整形できるので、そちらを使います。
<?php // ... $dom = new \DOMDocument(); $dom->loadXml($xml->asXML()); // formatOutputオプションにtrueを指定 $dom->formatOutput = true; echo $dom->saveXml();
<?xml version="1.0"?> <services xmlns:nequal="http://nequal.jp/schema"> <nequal:service> <nequal:name>Openpear</nequal:name> <nequal:uri>http://openpear.org/</nequal:uri> </nequal:service> <nequal:service> <nequal:name>DEADLINETIMER ジェネレーター</nequal:name> <nequal:uri>http://deadlinetimer.com/</nequal:uri> </nequal:service> </services>
できあがり。PHP 5.3.3でやっているのですが、5.2系でも同じようにできると思います(調べてませんけど)。
調べ方
上記で書いた方法がわかるまでに、色々な経緯がありました。そもそもSimpleXMLでは名前空間に属した要素は出力できないんではないかとすら。
で、マニュアルみてもよくわからないときに僕がまずすることは、PHPのテストをみることです。
とりあえず手元にphp-5.3.2のソースがあったので、そこからSimpleXMLのテストコードを探します。
コア部分のコードはZendディレクトリ、ライブラリなどはextディレクトリに大体あります。SimpleXMLはたぶんextディレクトリに入っていそうなので、ext/simplexmlがないかみてみます。
$ ls ext/simplexml CREDITS README* config.m4 config.w32 examples/ php_simplexml.h php_simplexml_exports.h* simplexml.c simplexml.dsp sxe.c* sxe.h* tests/
やはりありました。一番右にtestsディレクトリがありますが、こいつの中にテストが入っています。.phpt拡張子のファイルがPHPのテストファイルです。lsしたらいっぱいあったので、そこから探します。
名前空間に関連するのでたぶん「namespace」という文字が使われていること、出力なのでasXML()メソッドを呼び出していることを考えてgrepかけてみます。
$ cd ext/simplexml $ grep -rinl namespace *.phpt | xargs grep -rnl 'asXML' 031.phpt
たまたまでしょうが、1つに絞り込まれました。031.phptをみてみると、addChild()メソッドに関するテストが書かれているファイルでした。ここから情報を探ります。
--EXPECTF-- Warning: SimpleXMLElement::addAttribute(): Attribute already exists in %s031.php on line %d Warning: SimpleXMLElement::addChild(): Cannot add element to attributes in %s031.php on line %d <?xml version="1.0"?> <root xmlns:s="urn::test" xmlns:t="urn::test-t" xmlns:v="urn::test-v" s:att1="b" att1="a" v:att11="xxx" att2="no-ns"> <child1>test</child1> <child1>test 2</child1> <s:child3/> <s:test1>myval</s:test1><m:test2 xmlns:m="urn::testnew">myval</m:test2><test3 xmlns="urn::testnew">myval</test3><test4>myval</test4><test5>myval</test5></root>
名前空間付きの要素を出力することはできるみたいですね。「
言いたいことは、フレームワークでもなんでもそうだけど、テストってやっぱ重要ですよね!ってことです。
全然関係ないけど、WEB+DB PRESS vol.58を読んでいて、Rails 3すげーなーって思いました。Symfony2と並べて考えると、RackまわりとActionDispatchはHttpFoundation、HttpKernel、Routerあたりがカバーできるかなって感じがするんだけど、モデルまわりが断然Railsの方がスマートというか...。
Validatorコンポーネントが遅い理由
Symfony2の状況を検証
IRC集会の時間が終わった後でしたが、@fivestr さんがいくつか検証してくれました。
* 現時点のコードだと、フォームのレンダリング処理に結構時間がかかる
http://www.symfony.gr.jp/blog/20100822-irc-06
* メタデータのキャッシュなどが行われていないようなので、今後の改善に期待。
検証に用いたスクリプトなどはGistにアップしました。
Address.php · GitHub
Validatorサービスをコンテナから読み込もうとすると、それだけで1.5秒くらいかかってしまうのです。いくらなんでも遅すぎるというわけで検証。
結論: 国際化ファイルの読み込みが遅い
XLIFFファイルのパースが遅いらしい。この処理が1.5秒くらいかかってるみたいです。これキャッシュすればいいんじゃないのかなーと。
Routingコンポーネントを参考にパッチを書こうかなと思い中。時間がとれれば・・・
メタデータのキャッシングは設定すればできるんだけども、DIコンテナの設定見てるとデフォルトではキャッシュしないのかな?
中を見ている限り、チューニング可能な部分は色々ありそうです。
sotarokを勝手に祝う会
PHP界の星、id:sotarokが結婚しました。
というわけでnequal主催のもと「sotarokを勝手に祝う会」を開催しちゃいます。
詳細および参加申し込みは下記URLからお願いします。
開催日は8/21(土)の18時からですが、申込期限が会場の都合で18日(水)の20時までとなっています。
期限まであとわずかとなっていますが、sotarokをお祝いしたいというたくさんの方々の参加をお待ちしています!
ドキュメント翻訳合宿
先週の土日にSymfonyユーザー会の方々(と他数名)とsymfony 1.4のドキュメント「Gentle Introduction」の翻訳をするため、長野で合宿をして参りました。
http://www.symfony.gr.jp/blog/20100801-symfony-translation-spa
僕はというと、土曜日は翻訳作業をしたものの、日曜日は別の作業が入ってしまいそちらにあたっていました。他の方々が黙々と翻訳を進める中、申し訳ないです。。。
ここ最近、上でも言った「別作業」でなかなか時間がとれず、ブログが全然更新できてないですね・・・。落ち着いた頃にはSymfony2もだいぶかたまってくるかと思うので、がんばります。
Symfony2のいいところ
ちょっと仕事が行き詰ったので、Symfony2のいいなーと思うところでも書いて頭をリフレッシュしよう。
ぱっと思いつくのはこのあたりですかね。
シンプルなアーキテクチャ
とにかくFilterがなくなるのがとてもうれしいです。Symfony2の流れってとてもシンプルで
- Kernelを起動
- Bundleの登録
- Containerの初期化
- 各Bundleの起動
- BundleごとにContainerの拡張など
- (Requestの生成)
- HttpKernelがRequestのハンドリング
- Responseの送信
これだけですよ。HttpKernelによるReqestのハンドリングもEventDispatcherを使っているので疎結合+様々な拡張が可能です。
DIコンテナ
DIコンテナほしいなとー、symfony使っててふと思ったのでこんなエントリー書いてるんですけど。factories.ymlとかもう色々面倒くさいんですもの...。
Twig組み込み
Twigってかテンプレートの継承がすごくいい感じです。Symfony2に合わせてTwigの拡張性も上がってるし、Twigいいですよ。
アクションの戻り値がResponseオブジェクト
sfExecutionFilterとかほんと忌々しい。ていうかsfConfigにテンプレート名いれるとかどうなの...。アクション実行後も色々よくわからんことされるより、アクションの内部で「Responseできました!」ってとこまで行く方が色々扱いやすいです。
redirectやforwardも今までは例外投げて止めるとかやっていましたが、今回はそれぞれのメソッドの戻り値としてResponseを返します。
ただ、アクション内で毎回ビューの指定とか書かなきゃいけないのでちょっと面倒です。変数の受け渡し方法も従来のものと変わるのですが、見通しは良くなるかなと思います。
Symfony2という名前について重要なお話し
So, please, as of now, whenever you write a blog post, a piece of documentation, a tweet, or a presentation, never write "Symfony 2" again. Use Symfony2 instead. That way, someone can search for "Symfony2 routing" and he will have only Symfony2 results.
symfony 1.x legacy website
Symfony 2って書くと検索性が下がるので、Symfony2って書けってお話です。Symfony2のことをさす時はSymfonyとバージョンの間にスペース入れちゃだめってことです。
そういうことなので、タグづけもsymfony2にしようと思います。タグは全部小文字っていう自分ルールがあるので小文字にしますが、symfony2って表記するのも間違いですからね。みなさん名前は正確に。