<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0">
	<channel>
		<docs>http://blogs.law.harvard.edu/tech/rss</docs>
		<language>ja-jp</language>
		<title>アシアルブログ</title>
		<link>http://blog.asial.co.jp/</link>
		<description>アシアルブログ最新投稿</description>
		<pubDate>Thu, 11 Mar 2010 18:27:13 +0900</pubDate>
		<lastBuildDate>Thu, 11 Mar 2010 19:22:14 +0900</lastBuildDate>
		<managingEditor>info@asial.co.jp</managingEditor>
		<webMaster>info@asial.co.jp</webMaster>
		<copyright>Copyright  All rights reserved.</copyright>
				<item>
			<pubDate>Thu, 11 Mar 2010 18:27:13 +0900</pubDate>
			<title>&lt;Symfony Componentsシリーズ(2)&gt; Symfony 2の秘密兵器: Request Handler</title>
			<link>http://blog.asial.co.jp/671</link>
			<description><![CDATA[ 小川です。<br />
<br />
本日第2弾となるこの記事では、今回はリクエストを受けてからレスポンスを返すまでの全体の流れを司る、Request Handlerというコンポーネントをご紹介します。<br />
<br />
Request Handlerを知るにあたって、Event Dispatcherコンポーネントを理解しておく必要があります。<br />
先に書いた<a href="http://blog.asial.co.jp/670">&lt;Symfony Componentsシリーズ(1)&gt; オブジェクトをつなぐEvent Dispatcher</a>という記事まだ読んでいない方は、そちらから読んでいただければと思います。(読んでもさっぱりわからない！というのであればご連絡ください・・・)<br />
<br />
◆ Request Handlerコンポーネントの構成<br />
<br />
まず、Request Handlerコンポーネントのディレクトリ構成です。以下のようになります。<br />
<br />
<ol class="boxcode-main no-number"><li>Components/RequestHandler:</li><li>Exception/<wbr />&nbsp;<wbr />&nbsp;Request.php<wbr />&nbsp;<wbr />&nbsp;RequestHandler.php<wbr />&nbsp;<wbr />&nbsp;RequestInterface.php<wbr />&nbsp;<wbr />&nbsp;Response.php<wbr />&nbsp;<wbr />&nbsp;ResponseInterface.php</li><li></li><li>Components/RequestHandler/Exception:</li><li>ForbiddenHttpException.php<wbr />&nbsp;<wbr />&nbsp;HttpException.php<wbr />&nbsp;<wbr />&nbsp;NotFoundHttpException.php<wbr />&nbsp;<wbr />&nbsp;UnauthorizedHttpException.php</li></ol><br />
symfony 1系には当然RequestクラスとResponseクラスがありますが、それらもまとめてこのRequest Handlerコンポーネントに含まれます。<br />
RequestInterfaceとResponseInterfaceというインターフェースがありますが、現在のところRequestInterfaceは空っぽ、ResponseInterfaceはsend()メソッドのみのインターフェースなので、RequestやResponseを自前のクラスや他のフレームワークのクラスを使いたい場合も大して難しくはないでしょう。<br />
ただSymfony上で使う場合は、RequestHandler以外の部分で様々なメソッドを使いますので、RequestやResponseを置き換えたい場合は、Request Handlerコンポーネント内のクラスを継承するのが無難かと思われます。<br />
<br />
Request Handler用の例外クラスが4つ定義されています。HttpExceptionは他3つの親となる例外クラスです。ただ、定義こそされていますがRequestHandlerが実際に処理中に投げるのはNotFoundHttpExceptionくらいです。その他にSPL例外を投げたりはします。<br />
<br />
<br />
◆ RequestHandlerクラス<br />
<br />
ではいよいよ、RequestHandlerクラスを見ていきましょう。全体の流れを司るクラスと聞くと非常に大きなクラスかと思われますが、実際にはコメントを含めても200行に満たない程度の、非常にシンプルなクラスです。<br />
実際に様々な処理を行っているわけではなく、本当に「アプリケーションの流れを形成」しているだけです。メソッドもコンストラクタを含めて4つだけしか定義されていません。<br />
<br />
<br />
* public function __construct(EventDispatcher $dispatcher)<br />
* public function handle(RequestInterface $request, $main = true)<br />
* public function handleRaw(RequestInterface $request, $main = true)<br />
* protected function filterResponse($response, $message, $main)<br />
<br />
これだけです。重要なのがhandle()メソッドです。引数をみると、RequestInterfaceを実装したクラスを受け取っているのがわかります。<br />
Symfony 2ではこのRequestHandlerをKernelが制御します。といっても、RequestHandlerのhandle()メソッドを呼び出す前にBundleを読み込んで、DIコンテナの設定をする程度で、後はRequest Handlerによって処理が流れていきます。<br />
<br />
ではより突っ込んでみていきましょう。<br />
<br />
<br />
◆ RequestHandler::handle()<br />
<br />
<ol class="php-main"><li><span class="php-inlinetags">&lt;?php</span><span class="php-code"></span></li>
<li><span class="php-code"><wbr />&nbsp;</span></li>
<li><span class="php-code"></span><span class="php-reserved">public</span><span class="php-code"><wbr />&nbsp;</span><span class="php-reserved">function</span><span class="php-code"><wbr />&nbsp;</span><span class="php-identifier">handle</span><span class="php-brackets">(</span><span class="php-identifier">RequestInterface</span><span class="php-code"><wbr />&nbsp;</span><span class="php-var">$request</span><span class="php-code">,<wbr />&nbsp;</span><span class="php-var">$main</span><span class="php-code"><wbr />&nbsp;=<wbr />&nbsp;</span><span class="php-reserved">true</span><span class="php-brackets">)</span><span class="php-code"></span></li>
<li><span class="php-code"></span><span class="php-brackets">{</span><span class="php-code"></span></li>
<li><span class="php-code"><wbr />&nbsp;<wbr />&nbsp;</span><span class="php-var">$main</span><span class="php-code"><wbr />&nbsp;=<wbr />&nbsp;</span><span class="php-brackets">(</span><span class="php-identifier">Boolean</span><span class="php-brackets">)</span><span class="php-code"><wbr />&nbsp;</span><span class="php-var">$main</span><span class="php-code">;</span></li>
<li><span class="php-code"><wbr />&nbsp;</span></li>
<li><span class="php-code"><wbr />&nbsp;<wbr />&nbsp;</span><span class="php-reserved">try</span><span class="php-code"></span></li>
<li><span class="php-code"><wbr />&nbsp;<wbr />&nbsp;</span><span class="php-brackets">{</span><span class="php-code"></span></li>
<li><span class="php-code"><wbr />&nbsp;<wbr />&nbsp;<wbr />&nbsp;<wbr />&nbsp;</span><span class="php-reserved">return</span><span class="php-code"><wbr />&nbsp;</span><span class="php-var">$this</span><span class="php-code">-&gt;</span><span class="php-identifier">handleRaw</span><span class="php-brackets">(</span><span class="php-var">$request</span><span class="php-code">,<wbr />&nbsp;</span><span class="php-var">$main</span><span class="php-brackets">)</span><span class="php-code">;</span></li>
<li><span class="php-code"><wbr />&nbsp;<wbr />&nbsp;</span><span class="php-brackets">}</span><span class="php-code"></span></li>
<li><span class="php-code"><wbr />&nbsp;<wbr />&nbsp;</span><span class="php-reserved">catch</span><span class="php-code"><wbr />&nbsp;</span><span class="php-brackets">(</span><span class="php-code">\</span><span class="php-identifier">Exception</span><span class="php-code"><wbr />&nbsp;</span><span class="php-var">$e</span><span class="php-brackets">)</span><span class="php-code"></span></li>
<li><span class="php-code"><wbr />&nbsp;<wbr />&nbsp;</span><span class="php-brackets">{</span><span class="php-code"></span></li>
<li><span class="php-code"><wbr />&nbsp;<wbr />&nbsp;<wbr />&nbsp;<wbr />&nbsp;</span><span class="php-comment">//<wbr />&nbsp;exception</span><span class="php-code"></span></li>
<li><span class="php-code"><wbr />&nbsp;<wbr />&nbsp;<wbr />&nbsp;<wbr />&nbsp;</span><span class="php-var">$event</span><span class="php-code"><wbr />&nbsp;=<wbr />&nbsp;</span><span class="php-var">$this</span><span class="php-code">-&gt;</span><span class="php-identifier">dispatcher</span><span class="php-code">-&gt;</span><span class="php-identifier">notifyUntil</span><span class="php-brackets">(</span><span class="php-reserved">new</span><span class="php-code"><wbr />&nbsp;</span><span class="php-identifier">Event</span><span class="php-brackets">(</span><span class="php-var">$this</span><span class="php-code">,<wbr />&nbsp;</span><span class="php-quotes">'</span><span class="php-string">core.exception</span><span class="php-quotes">'</span><span class="php-code">,<wbr />&nbsp;</span><span class="php-reserved">array</span><span class="php-brackets">(</span><span class="php-quotes">'</span><span class="php-string">main_request</span><span class="php-quotes">'</span><span class="php-code"><wbr />&nbsp;=&gt;<wbr />&nbsp;</span><span class="php-var">$main</span><span class="php-code">,<wbr />&nbsp;</span><span class="php-quotes">'</span><span class="php-string">request</span><span class="php-quotes">'</span><span class="php-code"><wbr />&nbsp;=&gt;<wbr />&nbsp;</span><span class="php-var">$request</span><span class="php-code">,<wbr />&nbsp;</span><span class="php-quotes">'</span><span class="php-string">exception</span><span class="php-quotes">'</span><span class="php-code"><wbr />&nbsp;=&gt;<wbr />&nbsp;</span><span class="php-var">$e</span><span class="php-brackets">)))</span><span class="php-code">;</span></li>
<li><span class="php-code"><wbr />&nbsp;<wbr />&nbsp;<wbr />&nbsp;<wbr />&nbsp;</span><span class="php-reserved">if</span><span class="php-code"><wbr />&nbsp;</span><span class="php-brackets">(</span><span class="php-var">$event</span><span class="php-code">-&gt;</span><span class="php-identifier">isProcessed</span><span class="php-brackets">())</span><span class="php-code"></span></li>
<li><span class="php-code"><wbr />&nbsp;<wbr />&nbsp;<wbr />&nbsp;<wbr />&nbsp;</span><span class="php-brackets">{</span><span class="php-code"></span></li>
<li><span class="php-code"><wbr />&nbsp;<wbr />&nbsp;<wbr />&nbsp;<wbr />&nbsp;<wbr />&nbsp;<wbr />&nbsp;</span><span class="php-reserved">return</span><span class="php-code"><wbr />&nbsp;</span><span class="php-var">$this</span><span class="php-code">-&gt;</span><span class="php-identifier">filterResponse</span><span class="php-brackets">(</span><span class="php-var">$event</span><span class="php-code">-&gt;</span><span class="php-identifier">getReturnValue</span><span class="php-brackets">()</span><span class="php-code">,<wbr />&nbsp;</span><span class="php-quotes">'</span><span class="php-string">A<wbr />&nbsp;&quot;core.exception&quot;<wbr />&nbsp;listener<wbr />&nbsp;returned<wbr />&nbsp;a<wbr />&nbsp;non<wbr />&nbsp;response<wbr />&nbsp;object.</span><span class="php-quotes">'</span><span class="php-code">,<wbr />&nbsp;</span><span class="php-var">$main</span><span class="php-brackets">)</span><span class="php-code">;</span></li>
<li><span class="php-code"><wbr />&nbsp;<wbr />&nbsp;<wbr />&nbsp;<wbr />&nbsp;</span><span class="php-brackets">}</span><span class="php-code"></span></li>
<li><span class="php-code"><wbr />&nbsp;</span></li>
<li><span class="php-code"><wbr />&nbsp;<wbr />&nbsp;<wbr />&nbsp;<wbr />&nbsp;</span><span class="php-reserved">throw</span><span class="php-code"><wbr />&nbsp;</span><span class="php-var">$e</span><span class="php-code">;</span></li>
<li><span class="php-code"><wbr />&nbsp;<wbr />&nbsp;</span><span class="php-brackets">}</span><span class="php-code"></span></li>
<li><span class="php-code"></span><span class="php-brackets">}</span></li></ol><br />
handleRaw()を呼び出して、戻り値をそのまま返すだけのメソッドです。handleRaw()の戻り値はResponseInterfaceを実装したオブジェクトになります。<br />
また、例外が発生した場合はcore.exceptionイベントを通知しています。ここでEventに対してisProcessed()とgetReturnValue()という2つのメソッドを実行しています。isProcessed()は登録してあるリスナーのどれかが処理を行ってtrueを返した場合にtrueを返します。つまりイベントに対して何かしらの処理がされたかをチェックするためのものです。getReturnValue()はリスナーが指定した戻り値を取得するためのものです。リスナーがreturnした値ではなく、リスナー側で$event->setReturnValue()を実行してセットされたものになります。<br />
<br />
Symfonyはここで、例外に対して例外用の画面を表示するためのレスポンスを作成して返します。filterResponse()メソッドを呼び出していますが、これはレスポンスを返す際に必ず通す処理で、レスポンスを返すためのイベントを通知するためのものです。このメソッドにはResponseInterfaceを実装したオブジェクトを渡さないと例外となるようです。詳しくは後ほど見ていきましょう。<br />
<br />
<br />
◆ RequestHandler::handleRaw()<br />
<br />
例外が起きた場合の処理はhandle()メソッドに任せるとして、正常なフローを一通り行うのがこのhandleRaw()です。<br />
<br />
ここでいうフローとは、ずばりイベントです。順番に次のようにイベントが呼び出されます。<br />
<br />
* core.request<br />
* core.load_controller<br />
* core.controller<br />
* core.view<br />
<br />
実際に処理を分割しながらみていきましょう。<br />
<br />
<br />
### core.request<br />
<br />
<ol class="php-main"><li><span class="php-inlinetags">&lt;?php</span><span class="php-code"></span></li>
<li><span class="php-code"></span><span class="php-comment">//<wbr />&nbsp;request</span><span class="php-code"></span></li>
<li><span class="php-code"></span><span class="php-var">$event</span><span class="php-code"><wbr />&nbsp;=<wbr />&nbsp;</span><span class="php-var">$this</span><span class="php-code">-&gt;</span><span class="php-identifier">dispatcher</span><span class="php-code">-&gt;</span><span class="php-identifier">notifyUntil</span><span class="php-brackets">(</span><span class="php-reserved">new</span><span class="php-code"><wbr />&nbsp;</span><span class="php-identifier">Event</span><span class="php-brackets">(</span><span class="php-var">$this</span><span class="php-code">,<wbr />&nbsp;</span><span class="php-quotes">'</span><span class="php-string">core.request</span><span class="php-quotes">'</span><span class="php-code">,</span></li>
<li><span class="php-code"><wbr />&nbsp;<wbr />&nbsp;<wbr />&nbsp;</span><span class="php-reserved">array</span><span class="php-brackets">(</span><span class="php-quotes">'</span><span class="php-string">main_request</span><span class="php-quotes">'</span><span class="php-code"><wbr />&nbsp;=&gt;<wbr />&nbsp;</span><span class="php-var">$main</span><span class="php-code">,<wbr />&nbsp;</span><span class="php-quotes">'</span><span class="php-string">request</span><span class="php-quotes">'</span><span class="php-code"><wbr />&nbsp;=&gt;<wbr />&nbsp;</span><span class="php-var">$request</span><span class="php-brackets">)))</span><span class="php-code">;</span></li>
<li><span class="php-code"></span><span class="php-reserved">if</span><span class="php-code"><wbr />&nbsp;</span><span class="php-brackets">(</span><span class="php-var">$event</span><span class="php-code">-&gt;</span><span class="php-identifier">isProcessed</span><span class="php-brackets">())</span><span class="php-code"></span></li>
<li><span class="php-code"></span><span class="php-brackets">{</span><span class="php-code"></span></li>
<li><span class="php-code"><wbr />&nbsp;<wbr />&nbsp;</span><span class="php-reserved">return</span><span class="php-code"><wbr />&nbsp;</span><span class="php-var">$this</span><span class="php-code">-&gt;</span><span class="php-identifier">filterResponse</span><span class="php-brackets">(</span><span class="php-var">$event</span><span class="php-code">-&gt;</span><span class="php-identifier">getReturnValue</span><span class="php-brackets">()</span><span class="php-code">,</span></li>
<li><span class="php-code"><wbr />&nbsp;<wbr />&nbsp;<wbr />&nbsp;</span><span class="php-quotes">'</span><span class="php-string">A<wbr />&nbsp;&quot;core.request&quot;<wbr />&nbsp;listener<wbr />&nbsp;returned<wbr />&nbsp;a<wbr />&nbsp;non<wbr />&nbsp;response<wbr />&nbsp;object.</span><span class="php-quotes">'</span><span class="php-code">,<wbr />&nbsp;</span><span class="php-var">$main</span><span class="php-brackets">)</span><span class="php-code">;</span></li>
<li><span class="php-code"></span><span class="php-brackets">}</span></li></ol><br />
Symfony側ではこのイベントが発生したら、まずルーティングが行われます。<br />
次のイベントがcore.load_controllerですので、コントローラを読み込む処理だと思われます。それまでに必要なことはこのイベントで行います。<br />
<br />
isProcessed()がtrueの場合は、イベントの戻り値をfilterResponse()に渡しています。<br />
filterResponse()に戻り値を渡しているということは、Responseオブジェクトを期待していることになります。<br />
コントローラを読み込む必要がないようなリクエストや、コントローラの処理そのものがキャッシュ場合などは処理を止めてレスポンスを返すのかなと思います。<br />
<br />
<br />
### core.load_controller<br />
<br />
<ol class="php-main"><li><span class="php-inlinetags">&lt;?php</span><span class="php-code"></span></li>
<li><span class="php-code"></span><span class="php-comment">//<wbr />&nbsp;load<wbr />&nbsp;controller</span><span class="php-code"></span></li>
<li><span class="php-code"></span><span class="php-var">$event</span><span class="php-code"><wbr />&nbsp;=<wbr />&nbsp;</span><span class="php-var">$this</span><span class="php-code">-&gt;</span><span class="php-identifier">dispatcher</span><span class="php-code">-&gt;</span><span class="php-identifier">notifyUntil</span><span class="php-brackets">(</span><span class="php-reserved">new</span><span class="php-code"><wbr />&nbsp;</span><span class="php-identifier">Event</span><span class="php-brackets">(</span><span class="php-var">$this</span><span class="php-code">,<wbr />&nbsp;</span><span class="php-quotes">'</span><span class="php-string">core.load_controller</span><span class="php-quotes">'</span><span class="php-code">,</span></li>
<li><span class="php-code"><wbr />&nbsp;<wbr />&nbsp;<wbr />&nbsp;</span><span class="php-reserved">array</span><span class="php-brackets">(</span><span class="php-quotes">'</span><span class="php-string">main_request</span><span class="php-quotes">'</span><span class="php-code"><wbr />&nbsp;=&gt;<wbr />&nbsp;</span><span class="php-var">$main</span><span class="php-code">,<wbr />&nbsp;</span><span class="php-quotes">'</span><span class="php-string">request</span><span class="php-quotes">'</span><span class="php-code"><wbr />&nbsp;=&gt;<wbr />&nbsp;</span><span class="php-var">$request</span><span class="php-brackets">)))</span><span class="php-code">;</span></li>
<li><span class="php-code"></span><span class="php-reserved">if</span><span class="php-code"><wbr />&nbsp;</span><span class="php-brackets">(</span><span class="php-code">!</span><span class="php-var">$event</span><span class="php-code">-&gt;</span><span class="php-identifier">isProcessed</span><span class="php-brackets">())</span><span class="php-code"></span></li>
<li><span class="php-code"></span><span class="php-brackets">{</span><span class="php-code"></span></li>
<li><span class="php-code"><wbr />&nbsp;<wbr />&nbsp;</span><span class="php-reserved">throw</span><span class="php-code"><wbr />&nbsp;</span><span class="php-reserved">new</span><span class="php-code"><wbr />&nbsp;</span><span class="php-identifier">NotFoundHttpException</span><span class="php-brackets">(</span><span class="php-quotes">'</span><span class="php-string">Unable<wbr />&nbsp;to<wbr />&nbsp;find<wbr />&nbsp;the<wbr />&nbsp;controller.</span><span class="php-quotes">'</span><span class="php-brackets">)</span><span class="php-code">;</span></li>
<li><span class="php-code"></span><span class="php-brackets">}</span><span class="php-code"></span></li>
<li><span class="php-code"><wbr />&nbsp;</span></li>
<li><span class="php-code"></span><span class="php-reserved">list</span><span class="php-brackets">(</span><span class="php-var">$controller</span><span class="php-code">,<wbr />&nbsp;</span><span class="php-var">$arguments</span><span class="php-brackets">)</span><span class="php-code"><wbr />&nbsp;=<wbr />&nbsp;</span><span class="php-var">$event</span><span class="php-code">-&gt;</span><span class="php-identifier">getReturnValue</span><span class="php-brackets">()</span><span class="php-code">;</span></li>
<li><span class="php-code"><wbr />&nbsp;</span></li>
<li><span class="php-code"></span><span class="php-comment">//<wbr />&nbsp;controller<wbr />&nbsp;must<wbr />&nbsp;be<wbr />&nbsp;a<wbr />&nbsp;callable</span><span class="php-code"></span></li>
<li><span class="php-code"></span><span class="php-reserved">if</span><span class="php-code"><wbr />&nbsp;</span><span class="php-brackets">(</span><span class="php-code">!</span><span class="php-identifier">is_callable</span><span class="php-brackets">(</span><span class="php-var">$controller</span><span class="php-brackets">))</span><span class="php-code"></span></li>
<li><span class="php-code"></span><span class="php-brackets">{</span><span class="php-code"></span></li>
<li><span class="php-code"><wbr />&nbsp;<wbr />&nbsp;</span><span class="php-reserved">throw</span><span class="php-code"><wbr />&nbsp;</span><span class="php-reserved">new</span><span class="php-code"><wbr />&nbsp;\</span><span class="php-identifier">LogicException</span><span class="php-brackets">(</span><span class="php-identifier">sprintf</span><span class="php-brackets">(</span><span class="php-quotes">'</span><span class="php-string">The<wbr />&nbsp;controller<wbr />&nbsp;must<wbr />&nbsp;be<wbr />&nbsp;a<wbr />&nbsp;callable<wbr />&nbsp;(%s).</span><span class="php-quotes">'</span><span class="php-code">,</span></li>
<li><span class="php-code"><wbr />&nbsp;<wbr />&nbsp;<wbr />&nbsp;<wbr />&nbsp;<wbr />&nbsp;</span><span class="php-identifier">var_export</span><span class="php-brackets">(</span><span class="php-var">$controller</span><span class="php-code">,<wbr />&nbsp;</span><span class="php-reserved">true</span><span class="php-brackets">)))</span><span class="php-code">;</span></li>
<li><span class="php-code"></span><span class="php-brackets">}</span></li></ol><br />
コントローラをロードする処理ですね。ここでisProcessed()がfalseの場合、つまりコントローラが読み込まれなかった場合はNotFoundHttpExceptionがスローされます。<br />
読み込んだ後は、イベントの戻り値にコントローラとその引数を設定する必要があるようです。<br />
コントローラは関数呼び出し可能でなければならないようですが、Symfonyでは通常、アクションとなるメソッドが指定されると思われます。<br />
シンプルにやりたい場合は、無名関数が戻り値でも十分だということですね。<br />
<br />
<br />
### core.controller<br />
<br />
<ol class="php-main"><li><span class="php-inlinetags">&lt;?php</span><span class="php-code"></span></li>
<li><span class="php-code"></span><span class="php-comment">//<wbr />&nbsp;controller</span><span class="php-code"></span></li>
<li><span class="php-code"></span><span class="php-var">$event</span><span class="php-code"><wbr />&nbsp;=<wbr />&nbsp;</span><span class="php-var">$this</span><span class="php-code">-&gt;</span><span class="php-identifier">dispatcher</span><span class="php-code">-&gt;</span><span class="php-identifier">notifyUntil</span><span class="php-brackets">(</span><span class="php-reserved">new</span><span class="php-code"><wbr />&nbsp;</span><span class="php-identifier">Event</span><span class="php-brackets">(</span><span class="php-var">$this</span><span class="php-code">,<wbr />&nbsp;</span><span class="php-quotes">'</span><span class="php-string">core.controller</span><span class="php-quotes">'</span><span class="php-code">,</span></li>
<li><span class="php-code"><wbr />&nbsp;<wbr />&nbsp;<wbr />&nbsp;</span><span class="php-reserved">array</span><span class="php-brackets">(</span><span class="php-quotes">'</span><span class="php-string">main_request</span><span class="php-quotes">'</span><span class="php-code"><wbr />&nbsp;=&gt;<wbr />&nbsp;</span><span class="php-var">$main</span><span class="php-code">,<wbr />&nbsp;</span><span class="php-quotes">'</span><span class="php-string">request</span><span class="php-quotes">'</span><span class="php-code"><wbr />&nbsp;=&gt;<wbr />&nbsp;</span><span class="php-var">$request</span><span class="php-code">,</span></li>
<li><span class="php-code"><wbr />&nbsp;<wbr />&nbsp;<wbr />&nbsp;</span><span class="php-quotes">'</span><span class="php-string">controller</span><span class="php-quotes">'</span><span class="php-code"><wbr />&nbsp;=&gt;<wbr />&nbsp;&amp;</span><span class="php-var">$controller</span><span class="php-code">,<wbr />&nbsp;</span><span class="php-quotes">'</span><span class="php-string">arguments</span><span class="php-quotes">'</span><span class="php-code"><wbr />&nbsp;=&gt;<wbr />&nbsp;&amp;</span><span class="php-var">$arguments</span><span class="php-brackets">)))</span><span class="php-code">;</span></li>
<li><span class="php-code"></span><span class="php-reserved">if</span><span class="php-code"><wbr />&nbsp;</span><span class="php-brackets">(</span><span class="php-var">$event</span><span class="php-code">-&gt;</span><span class="php-identifier">isProcessed</span><span class="php-brackets">())</span><span class="php-code"></span></li>
<li><span class="php-code"></span><span class="php-brackets">{</span><span class="php-code"></span></li>
<li><span class="php-code"><wbr />&nbsp;<wbr />&nbsp;</span><span class="php-reserved">try</span><span class="php-code"></span></li>
<li><span class="php-code"><wbr />&nbsp;<wbr />&nbsp;</span><span class="php-brackets">{</span><span class="php-code"></span></li>
<li><span class="php-code"><wbr />&nbsp;<wbr />&nbsp;<wbr />&nbsp;<wbr />&nbsp;</span><span class="php-reserved">return</span><span class="php-code"><wbr />&nbsp;</span><span class="php-var">$this</span><span class="php-code">-&gt;</span><span class="php-identifier">filterResponse</span><span class="php-brackets">(</span><span class="php-var">$event</span><span class="php-code">-&gt;</span><span class="php-identifier">getReturnValue</span><span class="php-brackets">()</span><span class="php-code">,</span></li>
<li><span class="php-code"><wbr />&nbsp;<wbr />&nbsp;<wbr />&nbsp;<wbr />&nbsp;<wbr />&nbsp;<wbr />&nbsp;<wbr />&nbsp;</span><span class="php-quotes">'</span><span class="php-string">A<wbr />&nbsp;&quot;core.controller&quot;<wbr />&nbsp;listener<wbr />&nbsp;returned<wbr />&nbsp;a<wbr />&nbsp;non<wbr />&nbsp;response<wbr />&nbsp;object.</span><span class="php-quotes">'</span><span class="php-code">,<wbr />&nbsp;</span><span class="php-var">$main</span><span class="php-brackets">)</span><span class="php-code">;</span></li>
<li><span class="php-code"><wbr />&nbsp;<wbr />&nbsp;</span><span class="php-brackets">}</span><span class="php-code"></span></li>
<li><span class="php-code"><wbr />&nbsp;<wbr />&nbsp;</span><span class="php-reserved">catch</span><span class="php-code"><wbr />&nbsp;</span><span class="php-brackets">(</span><span class="php-code">\</span><span class="php-identifier">Exception</span><span class="php-code"><wbr />&nbsp;</span><span class="php-var">$e</span><span class="php-brackets">)</span><span class="php-code"></span></li>
<li><span class="php-code"><wbr />&nbsp;<wbr />&nbsp;</span><span class="php-brackets">{</span><span class="php-code"></span></li>
<li><span class="php-code"><wbr />&nbsp;<wbr />&nbsp;<wbr />&nbsp;<wbr />&nbsp;</span><span class="php-var">$retval</span><span class="php-code"><wbr />&nbsp;=<wbr />&nbsp;</span><span class="php-var">$event</span><span class="php-code">-&gt;</span><span class="php-identifier">getReturnValue</span><span class="php-brackets">()</span><span class="php-code">;</span></li>
<li><span class="php-code"><wbr />&nbsp;<wbr />&nbsp;</span><span class="php-brackets">}</span><span class="php-code"></span></li>
<li><span class="php-code"></span><span class="php-brackets">}</span><span class="php-code"></span></li>
<li><span class="php-code"></span><span class="php-reserved">else</span><span class="php-code"></span></li>
<li><span class="php-code"></span><span class="php-brackets">{</span><span class="php-code"></span></li>
<li><span class="php-code"><wbr />&nbsp;<wbr />&nbsp;</span><span class="php-comment">//<wbr />&nbsp;call<wbr />&nbsp;controller</span><span class="php-code"></span></li>
<li><span class="php-code"><wbr />&nbsp;<wbr />&nbsp;</span><span class="php-var">$retval</span><span class="php-code"><wbr />&nbsp;=<wbr />&nbsp;</span><span class="php-identifier">call_user_func_array</span><span class="php-brackets">(</span><span class="php-var">$controller</span><span class="php-code">,<wbr />&nbsp;</span><span class="php-var">$arguments</span><span class="php-brackets">)</span><span class="php-code">;</span></li>
<li><span class="php-code"></span><span class="php-brackets">}</span></li></ol><br />
core.load_controllerで返ってきた$controllerを実際に実行するのが、core.controllerです。<br />
このイベントにリスナーを指定しなくても、コントローラの呼び出しは行われるようです。<br />
<br />
<br />
### core.view<br />
<br />
<ol class="php-main"><li><span class="php-code">//<wbr />&nbsp;view</span></li>
<li><span class="php-code"></span><span class="php-inlinetags">&lt;?php</span><span class="php-code"></span></li>
<li><span class="php-code"></span><span class="php-var">$event</span><span class="php-code"><wbr />&nbsp;=<wbr />&nbsp;</span><span class="php-var">$this</span><span class="php-code">-&gt;</span><span class="php-identifier">dispatcher</span><span class="php-code">-&gt;</span><span class="php-identifier">filter</span><span class="php-brackets">(</span><span class="php-reserved">new</span><span class="php-code"><wbr />&nbsp;</span><span class="php-identifier">Event</span><span class="php-brackets">(</span><span class="php-var">$this</span><span class="php-code">,<wbr />&nbsp;</span><span class="php-quotes">'</span><span class="php-string">core.view</span><span class="php-quotes">'</span><span class="php-code">,</span></li>
<li><span class="php-code"><wbr />&nbsp;<wbr />&nbsp;<wbr />&nbsp;</span><span class="php-reserved">array</span><span class="php-brackets">(</span><span class="php-quotes">'</span><span class="php-string">main_request</span><span class="php-quotes">'</span><span class="php-code"><wbr />&nbsp;=&gt;<wbr />&nbsp;</span><span class="php-var">$main</span><span class="php-brackets">))</span><span class="php-code">,<wbr />&nbsp;</span><span class="php-var">$retval</span><span class="php-brackets">)</span><span class="php-code">;</span></li>
<li><span class="php-code"><wbr />&nbsp;</span></li>
<li><span class="php-code"></span><span class="php-reserved">return</span><span class="php-code"><wbr />&nbsp;</span><span class="php-var">$this</span><span class="php-code">-&gt;</span><span class="php-identifier">filterResponse</span><span class="php-brackets">(</span><span class="php-var">$event</span><span class="php-code">-&gt;</span><span class="php-identifier">getReturnValue</span><span class="php-brackets">()</span><span class="php-code">,</span></li>
<li><span class="php-code"><wbr />&nbsp;<wbr />&nbsp;<wbr />&nbsp;</span><span class="php-identifier">sprintf</span><span class="php-brackets">(</span><span class="php-quotes">'</span><span class="php-string">The<wbr />&nbsp;controller<wbr />&nbsp;must<wbr />&nbsp;return<wbr />&nbsp;a<wbr />&nbsp;response<wbr />&nbsp;(instead<wbr />&nbsp;of<wbr />&nbsp;%s).</span><span class="php-quotes">'</span><span class="php-code">,</span></li>
<li><span class="php-code"><wbr />&nbsp;<wbr />&nbsp;<wbr />&nbsp;<wbr />&nbsp;<wbr />&nbsp;</span><span class="php-identifier">is_object</span><span class="php-brackets">(</span><span class="php-var">$event</span><span class="php-code">-&gt;</span><span class="php-identifier">getReturnValue</span><span class="php-brackets">())</span><span class="php-code"><wbr />&nbsp;?</span></li>
<li><span class="php-code"><wbr />&nbsp;<wbr />&nbsp;<wbr />&nbsp;<wbr />&nbsp;<wbr />&nbsp;<wbr />&nbsp;<wbr />&nbsp;</span><span class="php-quotes">'</span><span class="php-string">an<wbr />&nbsp;object<wbr />&nbsp;of<wbr />&nbsp;class<wbr />&nbsp;</span><span class="php-quotes">'</span><span class="php-code">.</span><span class="php-identifier">get_class</span><span class="php-brackets">(</span><span class="php-var">$e</span><span class="php-code">-&gt;</span><span class="php-identifier">getReturnValue</span><span class="php-brackets">())</span><span class="php-code"><wbr />&nbsp;:</span></li>
<li><span class="php-code"><wbr />&nbsp;<wbr />&nbsp;<wbr />&nbsp;<wbr />&nbsp;<wbr />&nbsp;<wbr />&nbsp;<wbr />&nbsp;</span><span class="php-identifier">str_replace</span><span class="php-brackets">(</span><span class="php-quotes">&quot;</span><span class="php-special">\n</span><span class="php-quotes">&quot;</span><span class="php-code">,<wbr />&nbsp;</span><span class="php-quotes">''</span><span class="php-code">,<wbr />&nbsp;</span><span class="php-identifier">var_export</span><span class="php-brackets">(</span><span class="php-var">$event</span><span class="php-code">-&gt;</span><span class="php-identifier">getReturnValue</span><span class="php-brackets">()</span><span class="php-code">,<wbr />&nbsp;</span><span class="php-reserved">true</span><span class="php-brackets">))</span><span class="php-code"></span></li>
<li><span class="php-code"><wbr />&nbsp;<wbr />&nbsp;<wbr />&nbsp;<wbr />&nbsp;</span><span class="php-brackets">)</span><span class="php-code">,</span></li>
<li><span class="php-code"><wbr />&nbsp;<wbr />&nbsp;<wbr />&nbsp;</span><span class="php-var">$main</span><span class="php-brackets">)</span><span class="php-code">;</span></li></ol><br />
handleRaw()から通知される最後のイベントです。先ほどcore.controllerを行った結果をフィルタリングしています。その後、イベントの戻り値をfilterResponse()に渡しています。<br />
filter()にリスナーが登録されていない場合、filter()に指定した第2引数がそのまま戻り値として設定されます。<br />
<br />
<br />
説明を一切しなかったのですが、handleとhandleRaw()には第2引数に$mainというものがあります。これはデフォルトではtrueです。falseになるのはどういった状況なのでしょうか。<br />
symfonyをよく知っている方はもしかしたらなんとなくわかるかもしれません。これがfalseで呼び出されるのは、forwardが行われた時です。<br />
Symfonyのforwardとは、同一リクエストの中で、特定のアクションから別のアクションを呼び出す処理のことです。forwardが行われた場合は、再度handle()が呼び出されるようになります。<br />
<br />
<br />
◆ RequestHandler::filterResponse()<br />
<br />
<ol class="php-main"><li><span class="php-inlinetags">&lt;?php</span><span class="php-code"></span></li>
<li><span class="php-code"><wbr />&nbsp;</span></li>
<li><span class="php-code"></span><span class="php-reserved">protected</span><span class="php-code"><wbr />&nbsp;</span><span class="php-reserved">function</span><span class="php-code"><wbr />&nbsp;</span><span class="php-identifier">filterResponse</span><span class="php-brackets">(</span><span class="php-var">$response</span><span class="php-code">,<wbr />&nbsp;</span><span class="php-var">$message</span><span class="php-code">,<wbr />&nbsp;</span><span class="php-var">$main</span><span class="php-brackets">)</span><span class="php-code"></span></li>
<li><span class="php-code"></span><span class="php-brackets">{</span><span class="php-code"></span></li>
<li><span class="php-code"><wbr />&nbsp;<wbr />&nbsp;</span><span class="php-reserved">if</span><span class="php-code"><wbr />&nbsp;</span><span class="php-brackets">(</span><span class="php-code">!</span><span class="php-var">$response</span><span class="php-code"><wbr />&nbsp;</span><span class="php-identifier">instanceof</span><span class="php-code"><wbr />&nbsp;</span><span class="php-identifier">ResponseInterface</span><span class="php-brackets">)</span><span class="php-code"></span></li>
<li><span class="php-code"><wbr />&nbsp;<wbr />&nbsp;</span><span class="php-brackets">{</span><span class="php-code"></span></li>
<li><span class="php-code"><wbr />&nbsp;<wbr />&nbsp;<wbr />&nbsp;<wbr />&nbsp;</span><span class="php-reserved">throw</span><span class="php-code"><wbr />&nbsp;</span><span class="php-reserved">new</span><span class="php-code"><wbr />&nbsp;\</span><span class="php-identifier">RuntimeException</span><span class="php-brackets">(</span><span class="php-var">$message</span><span class="php-brackets">)</span><span class="php-code">;</span></li>
<li><span class="php-code"><wbr />&nbsp;<wbr />&nbsp;</span><span class="php-brackets">}</span><span class="php-code"></span></li>
<li><span class="php-code"><wbr />&nbsp;</span></li>
<li><span class="php-code"><wbr />&nbsp;<wbr />&nbsp;</span><span class="php-var">$event</span><span class="php-code"><wbr />&nbsp;=<wbr />&nbsp;</span><span class="php-var">$this</span><span class="php-code">-&gt;</span><span class="php-identifier">dispatcher</span><span class="php-code">-&gt;</span><span class="php-identifier">filter</span><span class="php-brackets">(</span><span class="php-reserved">new</span><span class="php-code"><wbr />&nbsp;</span><span class="php-identifier">Event</span><span class="php-brackets">(</span><span class="php-var">$this</span><span class="php-code">,<wbr />&nbsp;</span><span class="php-quotes">'</span><span class="php-string">core.response</span><span class="php-quotes">'</span><span class="php-code">,<wbr />&nbsp;</span><span class="php-reserved">array</span><span class="php-brackets">(</span><span class="php-quotes">'</span><span class="php-string">main_request</span><span class="php-quotes">'</span><span class="php-code"><wbr />&nbsp;=&gt;<wbr />&nbsp;</span><span class="php-var">$main</span><span class="php-brackets">))</span><span class="php-code">,<wbr />&nbsp;</span><span class="php-var">$response</span><span class="php-brackets">)</span><span class="php-code">;</span></li>
<li><span class="php-code"><wbr />&nbsp;<wbr />&nbsp;</span><span class="php-var">$response</span><span class="php-code"><wbr />&nbsp;=<wbr />&nbsp;</span><span class="php-var">$event</span><span class="php-code">-&gt;</span><span class="php-identifier">getReturnValue</span><span class="php-brackets">()</span><span class="php-code">;</span></li>
<li><span class="php-code"><wbr />&nbsp;</span></li>
<li><span class="php-code"><wbr />&nbsp;<wbr />&nbsp;</span><span class="php-reserved">if</span><span class="php-code"><wbr />&nbsp;</span><span class="php-brackets">(</span><span class="php-code">!</span><span class="php-var">$response</span><span class="php-code"><wbr />&nbsp;</span><span class="php-identifier">instanceof</span><span class="php-code"><wbr />&nbsp;</span><span class="php-identifier">ResponseInterface</span><span class="php-brackets">)</span><span class="php-code"></span></li>
<li><span class="php-code"><wbr />&nbsp;<wbr />&nbsp;</span><span class="php-brackets">{</span><span class="php-code"></span></li>
<li><span class="php-code"><wbr />&nbsp;<wbr />&nbsp;<wbr />&nbsp;<wbr />&nbsp;</span><span class="php-reserved">throw</span><span class="php-code"><wbr />&nbsp;</span><span class="php-reserved">new</span><span class="php-code"><wbr />&nbsp;\</span><span class="php-identifier">RuntimeException</span><span class="php-brackets">(</span><span class="php-quotes">'</span><span class="php-string">A<wbr />&nbsp;&quot;core.response&quot;<wbr />&nbsp;listener<wbr />&nbsp;returned<wbr />&nbsp;a<wbr />&nbsp;non<wbr />&nbsp;response<wbr />&nbsp;object.</span><span class="php-quotes">'</span><span class="php-brackets">)</span><span class="php-code">;</span></li>
<li><span class="php-code"><wbr />&nbsp;<wbr />&nbsp;</span><span class="php-brackets">}</span><span class="php-code"></span></li>
<li><span class="php-code"><wbr />&nbsp;</span></li>
<li><span class="php-code"><wbr />&nbsp;<wbr />&nbsp;</span><span class="php-reserved">return</span><span class="php-code"><wbr />&nbsp;</span><span class="php-var">$response</span><span class="php-code">;</span></li>
<li><span class="php-code"></span><span class="php-brackets">}</span></li></ol><br />
最後にご紹介するのが、散々出てきたfilterResponse()です。まず第1引数がResponseInterfaceを実装していなければ、実行時例外であるRuntimeExceptionが投げられます。<br />
その後、レスポンスオブジェクトに対してfilterを通知しています。handle()の戻り値は例外が最終的にキャッチされなかった場合を除き、常にこのメソッドを通るため、確実にResponseInterfaceを実装したオブジェクトになります。<br />
<br />
<br />
Request Handlerコンポーネントの紹介は以上です。説明の途中でSymfonyがイベントに対する処理についていくつか記述している箇所があります。<br />
実際にフレームワークとしてコントローラまわりなどの処理は、Symfony\Framework\WebBundleというBundleに含まれています。このBundleの中にListenerというディレクトリがあり、そこにいくつかのイベントリスナーが用意されています。これらがSymfonyとしての流れを実際に処理しています。<br />
そこを具体的に話し出すと、この記事が終わらなくなってしまうので本日はご紹介しませんが、そこで行っていること基本的な内容は書いてある通りです。<br />
<br />
<br />
さて、長くなりましたが、Symfony 2の秘密兵器であるRequest Handlerコンポーネントの説明は以上になります。<br />
イベントによって流れが作られているため、非常に柔軟になっています。この仕組みを知っておくことで、多少は全体が見えやすくなるかと思います。<br />
<br />
<br />
さて、今回タイトルに、Symfony Componentsシリーズと入れています。今後も様々なコンポーネントを紹介していきたいと思っています。次は重要性を考えるとDependency Injectionでしょうか。Templatingは自分があまり触っていないため、もっと勉強してからになりそうです。それでは皆さま、次回をお楽しみに！ ]]></description>
			<author>小川雄大</author>
			<category>Tech</category>
			<guid isPermaLink="true">http://blog.asial.co.jp/671</guid>
		</item>
				<item>
			<pubDate>Thu, 11 Mar 2010 18:25:02 +0900</pubDate>
			<title>&lt;Symfony Componentsシリーズ(1)&gt; オブジェクトをつなぐEvent Dispatcher</title>
			<link>http://blog.asial.co.jp/670</link>
			<description><![CDATA[ こんにちは。小川です。<br />
<br />
先日<a href="http://blog.asial.co.jp/669">Symfony 2のアプリケーション構成を読む</a>という記事で、Symfony 2の大まかなアプリケーションのディレクトリ構成と、KernelやBundleという存在について書きました。Symfony 2を語る上でSymfony Componentsの存在はかかせません。本日は一挙2本立て！Symfony Componentsの中でも特に重要になるEvent DispatcherコンポーネントとRequest Handlerコンポーネントをご紹介します。今回ご紹介するのはEvent Dispatcherコンポーネントです。<br />
<br />
ちなみに本日2つ目の記事はこちらです<br />
<a href="http://blog.asial.co.jp/671">&lt;Symfony Componentsシリーズ&gt; Symfony 2の秘密兵器: Request Handler</a><br />
<br />
◆ Symfony Components<br />
<br />
はじめに、コンポーネントについてご存じない方のためにコンポーネントについて説明します。symfony 1系はオールインワンのフレームワークでした。その中から単体でも使える機能、symfony 1.4の中からいくつか挙げると、Yamlパーサー/ダンパー、ルーティング、フォームなどといったものを独立させたものがコンポーネントです。現在、GitHubにて開発されている<a href="http://github.com/symfony/symfony">Symfonyのブランチ</a>の中には、次のようなコンポーネントが含まれています。<br />
<br />
* Console<br />
 - <a href="http://blog.asial.co.jp/654">コマンドライン・アプリケーション</a><br />
* DependencyInjection<br />
 - DIコンテナ<br />
* EventDispatcher<br />
 - Observerパターンの実装<br />
* OutputEscaper<br />
 - 出力の自動エスケープ<br />
* RequestHandler<br />
 - RequestからResponseまでの流れを統括<br />
* Routing<br />
 - ルーティングの制御<br />
* Templating<br />
 -フレキシブルなテンプレートエンジン<br />
* Yaml<br />
 -YAMLパーサー/ダンパー<br />
<br />
その他にも、FormやI18N、Fileなどが今後追加されると思われます。ただ、基本的には単体で動作するものの、一部のコンポーネントは他のコンポーネントを利用する場合があります。Dependency InjectionやRoutingにて設定ファイルをYAML形式で利用する場合はYAMLコンポーネントが必要になります。次の記事で紹介するRequest HandlerはEvent Dispatcherが必須になります。<br />
また、クラスのオートロードを前提とした作りになっています。<a href="/658">PHPの名前空間と主要フレームワークの対応について</a>という記事で大まかな名前空間のルールを定めてるお話をしましたが、それに準拠したオートロードの設定が必要です。もしないのであれば、Symfony\Foundation\UniversalClassLoaderクラスを利用するといいでしょう。<br />
<br />
これらのコンポーネントはそれぞれが非常に有用なものになっています。SymfonyがログやキャッシュにZend Frameworkを用いるように、Symfony以外のところで、Symfonyの超便利機能をつまみ食いできるようになっていますので、ぜひぜひ活用してほしいなあと思います。<br />
<br />
Symfonyの開発者であるFabien氏の<a href="http://www.slideshare.net/fabpot/symfony-components-3393116">プレゼン資料</a>も公開されていますので、そちらもぜひ参考にしてみてください。<br />
<br />
<br />
◆ Event Dispatcher<br />
<br />
Event Dispatcherはsymfony 1.2から実装された機能です。内容は現在の1.4に入ってるものも、2.0で搭載されるものも同じです。というのも、このEvent Dispatcherは2つのクラスのみで構成されます。詳細は後述します。<br />
<br />
みなさんJavaScriptはご存知ですか？例えば次のようなコードがあるとしましょう。<br />
<br />
<ol class="html-main"><li><span class="html-comment">&lt;!--<wbr />&nbsp;(1)<wbr />&nbsp;--&gt;</span><span class="html-code"></span></li>
<li><span class="html-code"></span><span class="html-brackets">&lt;</span><span class="html-reserved">input</span><span class="html-code"><wbr />&nbsp;</span><span class="html-var">type</span><span class="html-code">=</span><span class="html-quotes">&quot;</span><span class="html-string">button</span><span class="html-quotes">&quot;</span><span class="html-code"><wbr />&nbsp;</span><span class="html-var">id</span><span class="html-code">=</span><span class="html-quotes">&quot;</span><span class="html-string">some_button</span><span class="html-quotes">&quot;</span><span class="html-code"><wbr />&nbsp;</span><span class="html-var">value</span><span class="html-code">=</span><span class="html-quotes">&quot;</span><span class="html-string">click<wbr />&nbsp;me!</span><span class="html-quotes">&quot;</span><span class="html-code"><wbr />&nbsp;</span><span class="html-brackets">/&gt;</span><span class="html-code"></span></li>
<li><span class="html-code"><wbr />&nbsp;</span></li>
<li><span class="html-code"></span><span class="html-brackets">&lt;</span><span class="html-reserved">script</span><span class="html-code"><wbr />&nbsp;</span><span class="html-var">type</span><span class="html-code">=</span><span class="html-quotes">&quot;</span><span class="html-string">text/javascript</span><span class="html-quotes">&quot;</span><span class="html-brackets">&gt;</span><span class="html-code"></span></li>
<li><span class="html-code">//</span><span class="html-brackets">&lt;</span><span class="html-code">![</span><span class="html-var">CDATA</span><span class="html-code">[</span></li>
<li><span class="html-code"><wbr />&nbsp;</span></li>
<li><span class="html-code"><wbr />&nbsp;<wbr />&nbsp;//<wbr />&nbsp;(</span><span class="html-var">2</span><span class="html-code">)</span></li>
<li><span class="html-code"><wbr />&nbsp;<wbr />&nbsp;</span><span class="html-var">function</span><span class="html-code"><wbr />&nbsp;</span><span class="html-var">myListener</span><span class="html-code">(</span><span class="html-var">event</span><span class="html-code">)<wbr />&nbsp;{</span></li>
<li><span class="html-code"><wbr />&nbsp;<wbr />&nbsp;<wbr />&nbsp;<wbr />&nbsp;</span><span class="html-var">alert</span><span class="html-code">('</span><span class="html-var">Event</span><span class="html-code"><wbr />&nbsp;['<wbr />&nbsp;+<wbr />&nbsp;</span><span class="html-var">event</span><span class="html-code">.</span><span class="html-var">type</span><span class="html-code"><wbr />&nbsp;+<wbr />&nbsp;']<wbr />&nbsp;</span><span class="html-var">has</span><span class="html-code"><wbr />&nbsp;</span><span class="html-var">happened</span><span class="html-code">!'</span></li>
<li><span class="html-code"><wbr />&nbsp;<wbr />&nbsp;<wbr />&nbsp;<wbr />&nbsp;<wbr />&nbsp;<wbr />&nbsp;+<wbr />&nbsp;'<wbr />&nbsp;</span><span class="html-var">Button</span><span class="html-code">#'<wbr />&nbsp;+<wbr />&nbsp;</span><span class="html-var">event</span><span class="html-code">.</span><span class="html-var">target</span><span class="html-code">.</span><span class="html-var">id</span><span class="html-code"><wbr />&nbsp;+<wbr />&nbsp;'<wbr />&nbsp;</span><span class="html-var">was</span><span class="html-code"><wbr />&nbsp;</span><span class="html-var">clicked</span><span class="html-code">.');</span></li>
<li><span class="html-code"><wbr />&nbsp;<wbr />&nbsp;}</span></li>
<li><span class="html-code"><wbr />&nbsp;</span></li>
<li><span class="html-code"><wbr />&nbsp;<wbr />&nbsp;//<wbr />&nbsp;(</span><span class="html-var">3</span><span class="html-code">)</span></li>
<li><span class="html-code"><wbr />&nbsp;<wbr />&nbsp;</span><span class="html-var">document</span><span class="html-code">.</span><span class="html-var">getElementById</span><span class="html-code">('</span><span class="html-var">some_button</span><span class="html-code">').</span><span class="html-var">onclick</span><span class="html-code"><wbr />&nbsp;=<wbr />&nbsp;</span><span class="html-var">myListener</span><span class="html-code">;</span></li>
<li><span class="html-code"><wbr />&nbsp;</span></li>
<li><span class="html-code">//]]</span><span class="html-brackets">&gt;</span><span class="html-code"></span></li>
<li><span class="html-code"></span><span class="html-brackets">&lt;/</span><span class="html-reserved">script</span><span class="html-brackets">&gt;</span></li></ol><br />
内容としては、(1)で定義したボタンをクリックすると、ポップアップが出てくる、というものです。この仕組みがわかるのであれば、Event Dispatcherもすぐわかることでしょう。<br />
流れを説明しましょう。まず(1)です。これはただのinput要素です。idはsome_buttonになります。次に(2)と(3)です。(2)でmyListener()という関数を定義しています。これを(3)の部分で、idがsome_buttonの要素がクリックされたときに呼び出されるよう設定します。この場合、クリックをイベント、イベントに対して登録したmyListenerをイベントリスナーと呼びます。<br />
(3)で、関数そのものをonclick属性に登録しています。こうすることによって、clickされたときに自動的にmyListenerが呼び出され、引数としてeventオブジェクトが渡されます。<br />
JavaScriptでいうイベントとは、クリックやキーボード操作、ウィンドウの読み込みなど様々なものが定義されており、このeventオブジェクトには、何の操作が行われたか、どの要素に対して行われたか、マウスの座標はどこか、キーボードのどのキーが押されたのかなど、イベントによって様々なプロパティが定義されます。<br />
<br />
ここまでの仕組みをわかっていれば、Event Dispatcherもすぐ理解できるでしょう。Event Dispatcherには以下の2つのクラスが定義されています。<br />
<br />
* Event: (2)でmyListenerに渡している引数eventに当たる<br />
* EventDispatcher: イベントリスナーの管理やイベントの通知を行う、JavaScriptに当たる<br />
<br />
どのように使われるかみてみましょう。<br />
<br />
<ol class="php-main"><li><span class="php-inlinetags">&lt;?php</span><span class="php-code"></span></li>
<li><span class="php-code"></span><span class="php-identifier">use</span><span class="php-code"><wbr />&nbsp;</span><span class="php-identifier">Symfony</span><span class="php-code">\</span><span class="php-identifier">Components</span><span class="php-code">\</span><span class="php-identifier">EventDispatcher</span><span class="php-code">\</span><span class="php-identifier">Event</span><span class="php-code">;</span></li>
<li><span class="php-code"></span><span class="php-identifier">use</span><span class="php-code"><wbr />&nbsp;</span><span class="php-identifier">Symfony</span><span class="php-code">\</span><span class="php-identifier">Components</span><span class="php-code">\</span><span class="php-identifier">EventDispatcher</span><span class="php-code">\</span><span class="php-identifier">EventDispatcher</span><span class="php-code">;</span></li>
<li><span class="php-code"><wbr />&nbsp;</span></li>
<li><span class="php-code"></span><span class="php-reserved">class</span><span class="php-code"><wbr />&nbsp;</span><span class="php-identifier">Button</span><span class="php-code"></span></li>
<li><span class="php-code"></span><span class="php-brackets">{</span><span class="php-code"></span></li>
<li><span class="php-code"><wbr />&nbsp;<wbr />&nbsp;</span><span class="php-reserved">private</span><span class="php-code"><wbr />&nbsp;</span><span class="php-var">$id</span><span class="php-code">;</span></li>
<li><span class="php-code"><wbr />&nbsp;<wbr />&nbsp;</span><span class="php-reserved">private</span><span class="php-code"><wbr />&nbsp;</span><span class="php-var">$dispatcher</span><span class="php-code">;</span></li>
<li><span class="php-code"><wbr />&nbsp;</span></li>
<li><span class="php-code"><wbr />&nbsp;<wbr />&nbsp;</span><span class="php-reserved">public</span><span class="php-code"><wbr />&nbsp;</span><span class="php-reserved">function</span><span class="php-code"><wbr />&nbsp;</span><span class="php-identifier">__construct</span><span class="php-brackets">(</span><span class="php-identifier">EventDispatcher</span><span class="php-code"><wbr />&nbsp;</span><span class="php-var">$dispatcher</span><span class="php-code">,<wbr />&nbsp;</span><span class="php-var">$id</span><span class="php-brackets">)</span><span class="php-code"></span></li>
<li><span class="php-code"><wbr />&nbsp;<wbr />&nbsp;</span><span class="php-brackets">{</span><span class="php-code"></span></li>
<li><span class="php-code"><wbr />&nbsp;<wbr />&nbsp;<wbr />&nbsp;<wbr />&nbsp;</span><span class="php-var">$this</span><span class="php-code">-&gt;</span><span class="php-identifier">dispatcher</span><span class="php-code"><wbr />&nbsp;=<wbr />&nbsp;</span><span class="php-var">$dispatcher</span><span class="php-code">;</span></li>
<li><span class="php-code"><wbr />&nbsp;<wbr />&nbsp;<wbr />&nbsp;<wbr />&nbsp;</span><span class="php-var">$this</span><span class="php-code">-&gt;</span><span class="php-identifier">id</span><span class="php-code"><wbr />&nbsp;=<wbr />&nbsp;</span><span class="php-var">$id</span><span class="php-code">;</span></li>
<li><span class="php-code"><wbr />&nbsp;<wbr />&nbsp;</span><span class="php-brackets">}</span><span class="php-code"></span></li>
<li><span class="php-code"><wbr />&nbsp;</span></li>
<li><span class="php-code"><wbr />&nbsp;<wbr />&nbsp;</span><span class="php-reserved">public</span><span class="php-code"><wbr />&nbsp;</span><span class="php-reserved">function</span><span class="php-code"><wbr />&nbsp;</span><span class="php-identifier">getId</span><span class="php-brackets">()</span><span class="php-code"></span></li>
<li><span class="php-code"><wbr />&nbsp;<wbr />&nbsp;</span><span class="php-brackets">{</span><span class="php-code"></span></li>
<li><span class="php-code"><wbr />&nbsp;<wbr />&nbsp;<wbr />&nbsp;<wbr />&nbsp;</span><span class="php-reserved">return</span><span class="php-code"><wbr />&nbsp;</span><span class="php-var">$this</span><span class="php-code">-&gt;</span><span class="php-identifier">id</span><span class="php-code">;</span></li>
<li><span class="php-code"><wbr />&nbsp;<wbr />&nbsp;</span><span class="php-brackets">}</span><span class="php-code"></span></li>
<li><span class="php-code"><wbr />&nbsp;</span></li>
<li><span class="php-code"><wbr />&nbsp;<wbr />&nbsp;</span><span class="php-reserved">public</span><span class="php-code"><wbr />&nbsp;</span><span class="php-reserved">function</span><span class="php-code"><wbr />&nbsp;</span><span class="php-identifier">click</span><span class="php-brackets">()</span><span class="php-code"></span></li>
<li><span class="php-code"><wbr />&nbsp;<wbr />&nbsp;</span><span class="php-brackets">{</span><span class="php-code"></span></li>
<li><span class="php-code"><wbr />&nbsp;<wbr />&nbsp;<wbr />&nbsp;<wbr />&nbsp;</span><span class="php-comment">//<wbr />&nbsp;notify<wbr />&nbsp;button.click</span><span class="php-code"></span></li>
<li><span class="php-code"><wbr />&nbsp;<wbr />&nbsp;<wbr />&nbsp;<wbr />&nbsp;</span><span class="php-var">$this</span><span class="php-code">-&gt;</span><span class="php-identifier">dispatcher</span><span class="php-code">-&gt;</span><span class="php-identifier">notify</span><span class="php-brackets">(</span><span class="php-reserved">new</span><span class="php-code"><wbr />&nbsp;</span><span class="php-identifier">Event</span><span class="php-brackets">(</span><span class="php-var">$this</span><span class="php-code">,<wbr />&nbsp;</span><span class="php-quotes">'</span><span class="php-string">button.click</span><span class="php-quotes">'</span><span class="php-code">,<wbr />&nbsp;</span><span class="php-reserved">array</span><span class="php-brackets">(</span><span class="php-quotes">'</span><span class="php-string">foo</span><span class="php-quotes">'</span><span class="php-code"><wbr />&nbsp;=&gt;<wbr />&nbsp;</span><span class="php-quotes">'</span><span class="php-string">bar</span><span class="php-quotes">'</span><span class="php-brackets">)))</span><span class="php-code">;</span></li>
<li><span class="php-code"><wbr />&nbsp;<wbr />&nbsp;</span><span class="php-brackets">}</span><span class="php-code"></span></li>
<li><span class="php-code"></span><span class="php-brackets">}</span><span class="php-code"></span></li>
<li><span class="php-code"><wbr />&nbsp;</span></li>
<li><span class="php-code"></span><span class="php-comment">//<wbr />&nbsp;(2)</span><span class="php-code"></span></li>
<li><span class="php-code"></span><span class="php-reserved">function</span><span class="php-code"><wbr />&nbsp;</span><span class="php-identifier">myListener</span><span class="php-brackets">(</span><span class="php-identifier">Event</span><span class="php-code"><wbr />&nbsp;</span><span class="php-var">$event</span><span class="php-brackets">)</span><span class="php-code"></span></li>
<li><span class="php-code"></span><span class="php-brackets">{</span><span class="php-code"></span></li>
<li><span class="php-code"><wbr />&nbsp;<wbr />&nbsp;</span><span class="php-reserved">echo</span><span class="php-code"><wbr />&nbsp;</span><span class="php-identifier">sprintf</span><span class="php-brackets">(</span><span class="php-quotes">&quot;</span><span class="php-string">Event<wbr />&nbsp;[%s]<wbr />&nbsp;has<wbr />&nbsp;happend!</span><span class="php-quotes">&quot;</span><span class="php-code">,<wbr />&nbsp;</span><span class="php-var">$event</span><span class="php-code">-&gt;</span><span class="php-identifier">getName</span><span class="php-brackets">())</span><span class="php-code">;</span></li>
<li><span class="php-code"><wbr />&nbsp;</span></li>
<li><span class="php-code"><wbr />&nbsp;<wbr />&nbsp;</span><span class="php-var">$button</span><span class="php-code"><wbr />&nbsp;=<wbr />&nbsp;</span><span class="php-var">$event</span><span class="php-code">-&gt;</span><span class="php-identifier">getSubject</span><span class="php-brackets">()</span><span class="php-code">;</span></li>
<li><span class="php-code"><wbr />&nbsp;<wbr />&nbsp;</span><span class="php-reserved">echo</span><span class="php-code"><wbr />&nbsp;</span><span class="php-identifier">sprintf</span><span class="php-brackets">(</span><span class="php-quotes">&quot;</span><span class="php-string"><wbr />&nbsp;Button#%s<wbr />&nbsp;was<wbr />&nbsp;clicked.</span><span class="php-quotes">&quot;</span><span class="php-code">,<wbr />&nbsp;</span><span class="php-var">$button</span><span class="php-code">-&gt;</span><span class="php-identifier">getId</span><span class="php-brackets">())</span><span class="php-code">;</span></li>
<li><span class="php-code"><wbr />&nbsp;</span></li>
<li><span class="php-code"><wbr />&nbsp;<wbr />&nbsp;</span><span class="php-comment">//<wbr />&nbsp;custom<wbr />&nbsp;property</span><span class="php-code"></span></li>
<li><span class="php-code"><wbr />&nbsp;<wbr />&nbsp;</span><span class="php-var">$foo</span><span class="php-code"><wbr />&nbsp;=<wbr />&nbsp;</span><span class="php-var">$event</span><span class="php-brackets">[</span><span class="php-quotes">'</span><span class="php-string">foo</span><span class="php-quotes">'</span><span class="php-brackets">]</span><span class="php-code">;<wbr />&nbsp;</span><span class="php-comment">//<wbr />&nbsp;alias:<wbr />&nbsp;$event-&gt;getParameter('foo')</span><span class="php-code"></span></li>
<li><span class="php-code"><wbr />&nbsp;<wbr />&nbsp;</span><span class="php-reserved">echo</span><span class="php-code"><wbr />&nbsp;</span><span class="php-identifier">sprintf</span><span class="php-brackets">(</span><span class="php-quotes">&quot;</span><span class="php-string">(foo:<wbr />&nbsp;%s)</span><span class="php-quotes">&quot;</span><span class="php-code">,<wbr />&nbsp;</span><span class="php-var">$foo</span><span class="php-brackets">)</span><span class="php-code">;</span></li>
<li><span class="php-code"></span><span class="php-brackets">}</span><span class="php-code"></span></li>
<li><span class="php-code"><wbr />&nbsp;</span></li>
<li><span class="php-code"></span><span class="php-var">$dispatcher</span><span class="php-code"><wbr />&nbsp;=<wbr />&nbsp;</span><span class="php-reserved">new</span><span class="php-code"><wbr />&nbsp;</span><span class="php-identifier">EventDispatcher</span><span class="php-brackets">()</span><span class="php-code">;</span></li>
<li><span class="php-code"><wbr />&nbsp;</span></li>
<li><span class="php-code"></span><span class="php-comment">//<wbr />&nbsp;(1)</span><span class="php-code"></span></li>
<li><span class="php-code"></span><span class="php-var">$button</span><span class="php-code"><wbr />&nbsp;=<wbr />&nbsp;</span><span class="php-reserved">new</span><span class="php-code"><wbr />&nbsp;</span><span class="php-identifier">Button</span><span class="php-brackets">(</span><span class="php-var">$dispatcher</span><span class="php-code">,<wbr />&nbsp;</span><span class="php-quotes">'</span><span class="php-string">some_button</span><span class="php-quotes">'</span><span class="php-brackets">)</span><span class="php-code">;</span></li>
<li><span class="php-code"><wbr />&nbsp;</span></li>
<li><span class="php-code"></span><span class="php-var">$button</span><span class="php-code">-&gt;</span><span class="php-identifier">click</span><span class="php-brackets">()</span><span class="php-code">;</span></li>
<li><span class="php-code"></span><span class="php-comment">#<wbr />&nbsp;nothing<wbr />&nbsp;happens...</span><span class="php-code"></span></li>
<li><span class="php-code"><wbr />&nbsp;</span></li>
<li><span class="php-code"></span><span class="php-comment">//<wbr />&nbsp;(3)</span><span class="php-code"></span></li>
<li><span class="php-code"></span><span class="php-var">$dispatcher</span><span class="php-code">-&gt;</span><span class="php-identifier">connect</span><span class="php-brackets">(</span><span class="php-quotes">'</span><span class="php-string">button.click</span><span class="php-quotes">'</span><span class="php-code">,<wbr />&nbsp;</span><span class="php-quotes">'</span><span class="php-string">myListener</span><span class="php-quotes">'</span><span class="php-brackets">)</span><span class="php-code">;</span></li>
<li><span class="php-code"><wbr />&nbsp;</span></li>
<li><span class="php-code"></span><span class="php-var">$button</span><span class="php-code">-&gt;</span><span class="php-identifier">click</span><span class="php-brackets">()</span><span class="php-code">;</span></li>
<li><span class="php-code"></span><span class="php-comment">#<wbr />&nbsp;=&gt;<wbr />&nbsp;Event<wbr />&nbsp;[button.click]<wbr />&nbsp;has<wbr />&nbsp;happend!<wbr />&nbsp;Button#some_button<wbr />&nbsp;was<wbr />&nbsp;clicked.(foo:<wbr />&nbsp;bar)</span></li></ol><br />
クラスを書いたりしてたので長くなりました。先ほどのJavaScriptと極力同じようなものにしてみました。Buttonというクラスはボタン要素を表すイメージです。コンストラクタでEventDispatcherを受け取るようにしています。<br />
次にmyListener()関数を定義しています。これはJavaScriptの(2)と同じです。<br />
<br />
(1)ではButtonオブジェクトを生成しています。第2引数にボタンのIDを指定しています。先ほどと同じsome_buttonにします。<br />
この直後にclick()メソッドを呼び出しています。click()メソッドの内部で、 $this->dispatcher->notify(new Event($this, 'button.click')) としていますが、これはbutton.clickというイベントが発生したことをEventDispatcherに通知(notify)するためのものです。Eventオブジェクトを作る際、第1引数が通知元となるオブジェクト(サブジェクト)、第2引数がイベント名です。イベント名は通常.(ドット)で区切って名前空間を持たせます。第3引数は必須ではありませんが、好きなパラメータを連想配列で渡すことが可能です。<br />
<br />
その後、(3)で先ほど作ったEventDispatcherオブジェクトからconnect()というメソッドを実行しています。button.clickというイベントが実行されたらイベントリスナーとしてmyListener()関数を呼び出すための設定です。(3)でイベントリスナーの登録を行った後、再度click()メソッドを実行すると、またbutton.clickというイベントが発生します。今度はイベントリスナーとしてmyListener()が定義されていますので、myListener()が実行され、メッセージが出力されます。イベントリスナーの内部で引数$eventに対してgetName()とやるとイベント名の取得が、getSubject()メソッドを実行すると呼び出し元のオブジェクトが取得可能です。また配列形式でアクセスすると任意のパラメータが取得可能です。<br />
<br />
<br />
なんとなくEvent Dispatcherの仕組みがわかりましたか？注目してほしいのは、Buttonクラスの定義は一切変えずに、リスナー(myFunction()関数)を登録する前と後で処理の内容が変わるところです。<br />
通常Symfonyではフレームワーク全体で1つのEventDispatcherオブジェクトを共有しています。そしてSymfonyの内部の様々なところでイベントの通知が行われています。<br />
イベントを定義することで、要するにクラスの定義を変えずに処理を外部から組み込むことが可能になります。つまり、SymfonyにはSymfonyそのものを拡張するポイントがいくつも設置されています。<br />
<br />
通知方法は先ほどのnotify()も含めて3種類あります。<br />
<br />
* notify($event)<br />
 - 登録されている全てのリスナーに順番に通知<br />
* notifyUntil($event)<br />
 - 登録されているリスナーに順番に通知するが、リスナーがtrueを返した場合は通知を中断する<br />
* filter($event, $value)<br />
 - 登録されているリスナーに順番に$valueを渡して値のフィルタリングを行う<br />
<br />
Eventには戻り値の設定が可能です。例えばsymfony 1.4には、request.method_not_foundというイベントが定義されています。このイベントはRequestの__call()メソッドから通知されます。__call()は定義されていないメソッド呼び出しによって呼び出されるものです。request.method_not_foundイベントに対して、呼び出されたメソッド名に応じて特定の処理をして返すリスナーを定義しておけば、つまりはクラス定義をそのままに、メソッドの追加が可能になるわけです。この場合、メソッド名に対する処理が済んでおり後続のリスナーに通知する必要がないので、通知方法はnotifyUntilが用いられています。<br />
method_not_foundというイベントはこの他にも様々なところで定義されています。sfComponent(sfActionの親クラス)にはcomponent.method_not_found、responseにはresponse.method_not_foundが定義されています。<br />
<br />
filterは特定の値をフィルタリングするためのものです。例えばresponse.filter_contentイベントが挙げられます。このイベントではレスポンスとして返すHTMLなどの内容に対してフィルタリングをかけることが可能です。実際にsymfony 1.4ではこのイベントを利用して行っていることがあります。symfonyユーザーおなじみのWebデバッグツールバーをHTMLに組み込む処理です。この他だと、Formにbind()したときに、バインドした値をフィルタリングするためのform.filter_valuesなどがあります。<br />
<br />
Event Dispatcherを利用することにより、継承を使わずに様々な拡張が可能です。<br />
symfonyのドキュメントに<a href="http://www.symfony-project.org/reference/1_4/ja/15-Events">イベントの一覧</a>が用意されていますので、ぜひ1度見てみるといいかと思います。<br />
<br />
このEvent Dispatcherの仕組みを知ることで、symfonyでできることがぐっと広がると思います。<br />
<br />
<br />
では次に、Request Handlerコンポーネントをみていきましょう！<br />
<a href="http://blog.asial.co.jp/671">&lt;Symfony Componentsシリーズ(2)&gt; Symfony 2の秘密兵器: Request Handler</a> ]]></description>
			<author>小川雄大</author>
			<category>Tech</category>
			<guid isPermaLink="true">http://blog.asial.co.jp/670</guid>
		</item>
				<item>
			<pubDate>Thu, 04 Mar 2010 01:27:04 +0900</pubDate>
			<title>Symfony 2のアプリケーション構成を読む</title>
			<link>http://blog.asial.co.jp/669</link>
			<description><![CDATA[ こんにちは。小川です。<br />
今週からアシアルのオフィスの一部でフリーアドレス制度が導入されました。<br />
もしフリーアドレスを実施している会社にお勤めの方がいましたら、導入のアドバイスとか、おすすめのグッズなどがあれば教えてください！<br />
(今までは机の上にぬいぐるみなどを置いていたりしたのですが、移動が面倒になった分遊び心がもてなくなってしまい面白くないので、そのあたり工夫されていることがあればぜひ！)<br />
<br />
さて、今回のテーマは<a href="http://symfony-reloaded.org/">Symfony 2</a>です。先月なかごろにプレビュー版がリリースされました。ご存じの方もいらっしゃると思います。<br />
<br />
今回はSymfony 2の特徴に加え、実際にSymfony 2で作るアプリケーションの構成はどのようになるか、ということをお話ししたいと思います。<br />
<br />
------------------------------------------<br />
追記<br />
Symfony Componentsシリーズ始めました！<br />
<a href="http://blog.asial.co.jp/670">&lt;Symfony Componentsシリーズ(1)&gt; オブジェクトをつなぐEvent Dispatcher</a><br />
<a href="http://blog.asial.co.jp/671">&lt;Symfony Componentsシリーズ(2)&gt; Symfony 2の秘密兵器: Request Handler</a><br />
------------------------------------------<br />
<br />
<br />
まずはSymfony 2の特徴をざっくり書いてみたいと思います。<br />
<br />
◆ PHP 5.3以降に対応<br />
PHP 5.3といえば名前空間です。Symfony 2.0は名前空間を利用しています。これによりコードがシンプルになります。またクラス名や関数名の衝突を気にする必要がなくなります。<br />
<br />
◆シンプル・高速<br />
symfony 1系はよく重いといわれます。この点が大幅に改善されたようです。<br />
とりわけ変わっているのがアクションにたどり着くまでのプロセスです。アプリケーションの中核となるクラスがSymfony\Foundation\Kernelです。このクラス自身はとてもシンプルに作られています。<br />
また、Requestを受けてResponseの作成までの一連の処理を担うSymfony\Components\RequestHandler\RequestHandlerクラスもとてもシンプルに作られています。<br />
この2つのクラスがアプリケーション全体の流れを構成します。シンプルな流れの中に必要に応じて処理を組み込んでいく、というのがSymfony 2のスタンスとなります。<br />
<br />
◆DIコンテナ<br />
Symfony 2にはオブジェクトの依存性をなくすためのコンポーネントが2つあります。1つは以前から実装されていたEventDispatcherです。そして新たに実装されたのがDependencyInjectionというコンポーネントです。<br />
Dependency Injectionについては、Fabien氏のブログを読むと分かりやすいと思います。(<a href="http://fabien.potencier.org/article/11/what-is-dependency-injection">What is Dependency Injection?</a>)<br />
これによりフレームワークの拡張がより簡単になります。DIがよくわからない人も、多分使うようになるとわかるかなと思いますので、あまり心配しなくてもよいでしょう。<br />
<br />
◆Doctrine 2<br />
ORMであるDoctrineも新しいものになります。これも以前のDoctrineに比べてとても高速で軽量になります。Symfony自体の軽量化と合わせて、大きなパフォーマンスの改善が見込めそうです。<br />
<br />
◆Zend Framework<br />
Symfony 2から、ログとキャッシュにZend Frameworkを利用するようになります。SwiftMailerやDoctrineもそうですが、他のフレームワークとの連携を行うことでより品質の高いものができると思いますのでいいことかなと思います。<br />
<br />
<br />
さて、変更点をいくつかあげてみましたが、実際にSymfonyで作るアプリケーションがどのようになるのかはわからないかと思います。<br />
現在GitHub上に<a href="http://github.com/symfony/symfony-sandbox">sandbox</a>が上がっていますので、それを見てみるのが手っ取り早いと思います。<br />
<br />
sandboxにはHello Worldに毛が生えた程度のアプリケーションが最初から含まれています。<br />
では実際にディレクトリ構成やクラスの内部など、簡単に説明していきます。<br />
<br />
<br />
まずはsandboxのディレクトリ直下です。hello, src, webという3つのディレクトリがあると思います。ファイルはどうでもいいので無視です。<br />
<br />
<br />
### webディレクトリ<br />
<br />
一番とっつきやすいのはwebでしょう。従来のwebと同じように、ドキュメントルートとなるディレクトリです。<br />
中には見慣れたファイルがあると思います。index.phpとindex_dev.phpは依然と同じくフロントコントローラで、index_dev.phpは開発環境用のフロントコントローラにあたります。<br />
<br />
次にhelloとsrcです。どちらも今までのディレクトリ構成にはなかったものです。<br />
中身がシンプルなのはhelloディレクトリのほうなので、そちらから先にみていきます。<br />
<br />
<br />
### helloディレクトリ<br />
<br />
helloディレクトリの中身は次のようになっています。<br />
<br />
<ol class="boxcode-main no-number"><li>HelloKernel.php<wbr />&nbsp;<wbr />&nbsp;cache/<wbr />&nbsp;<wbr />&nbsp;config/<wbr />&nbsp;<wbr />&nbsp;console<wbr />&nbsp;<wbr />&nbsp;logs/</li></ol><br />
先ほど説明をしたKernelというものが出てきます。Kernelの中にはいくつかのメソッドが実装されています。簡単に説明します。<br />
<br />
◆registerRootDir()<br />
Kernelのルートとなるディレクトリです。またカーネルを配置してあるディレクトリ、ここではhelloがカーネルの名称、つまりアプリケーションの名称となります。<br />
<br />
◆registerBundles()<br />
Bundleとは日本語にすると束とか1つにまとめたものという意味です。このBundleはSymfony 2では非常に重要な役割を持ちます。<br />
このメソッドの中でZendBundleやDoctrineBundleを返しているのをみると、Bundleは従来のPluginのように思われるかもしれませんが、あながち間違いではないでしょう。<br />
このメソッドはアプリケーション = Kernelで必要となるBundleをKernel自身に登録するメソッドです。<br />
<br />
このメソッドの中で返している配列の最後に、Application\HelloBundle\Bundleというクラスを渡しています。<br />
Application\HelloBundleという名前空間から想像がつくかもしれませんが、これはアプリケーションの実態です。<br />
実際にBundleにどういったものが含まれるのかは後ほど説明します。<br />
<br />
◆registerBundleDirs()<br />
Bundleが配置してあるディレクトリを登録します。名前空間を修飾したクラス名のプレフィックスに応じて設定します。<br />
<br />
◆registerContainerConfiguration()<br />
DIコンテナのKernelごとの設定の読み込みを行います。基本的にはBundle単位で設定されていますが、必要に応じて追加・修正などを行うものと思われます。<br />
<br />
◆registerRoutes()<br />
ルーティングの設定の読み込みを行います。従来はアプリケーションごとにrouting.ymlがあり、もしプラグインでモジュールが提供されていればそれに対するルーティングを1つずつ定義するようになっていました。<br />
今回はBundle単位でrouting.ymlの定義が可能になっています。その設定を別のrouting.ymlからまとめて読み込む、ということが可能になりました。<br />
ルーティングの仕組み自体は基本的には従来と同じような感覚で使えるのかなと思っています。<br />
<br />
<br />
Kernelクラスをざっと説明しましたが、基本的にはこれらの内容が記述された状態で自動生成することになるのかなと思います。<br />
内部が柔軟な仕組みなので、こうしてある程度定義されているほうが修正がしやすいと思います。<br />
<br />
さて、Kernelクラスの説明が終わったら、あとは大したことありません。<br />
logsとcacheは名前の通りログとキャッシュが保存されます。キャッシュにはDIコンテナの情報やルーティング関連などが出力されるようです。<br />
前回同様にこのディレクトリにはWebサーバからの書き込みを許可するようにパーミッションの設定が必要になります。<br />
<br />
consoleというファイルはコマンドです。従来のsymfonyコマンドのように、このコマンド経由でスケルトンの生成などを行うことになると思います。<br />
また--shellオプションを付けると対話式のシェルとして実行可能なので、コマンドを連続して実行するときには便利かと思います。<br />
現在そこまでコマンドは多くないので、実装が固まってきたらより突っ込んでみていきたいと思います。<br />
<br />
helloディレクトリの中でほかに説明していないのは残すところconfigディレクトリだけになりましたが、すでに中に入っているファイルに関して触れてしまっていますね。<br />
Symfony 2にはDIコンテナがありますので、基本的にはDIコンテナに必要な修正をYAMLに書き足していくようになるのでしょうか。<br />
DIコンテナの設定をするためのファイルは1つでなくてもいいようなので、役割に応じてYAMLファイルを追加するようになるのかと思います。<br />
現状は必要最低限の設定ファイルだけを配置している可能性もありますし、このあたりの設定に関してはなんとも言えないところです。<br />
<br />
<br />
さて、helloディレクトリの中をざっくり説明しました。<br />
要するに、アプリケーションとしての設定関連をまとめたディレクトリでしょうか。<br />
Kernel次第でアプリケーションの内容をごっそり切りかえることも可能になります。<br />
読み込むBundle次第で、複雑なアプリケーションにもなりますし、簡潔なアプリケーションにもなるでしょう。<br />
従来のsymfonyでは小さなアプリケーションでも様々な処理を必要としていましたので、いくらでも簡潔に作れるというのは大きな魅力だと思います。<br />
<br />
<br />
### srcディレクトリ<br />
<br />
さて、残っているのはsrcディレクトリです。まずはディレクトリ構成を見てみます。<br />
<br />
<ol class="boxcode-main no-number"><li>Application/<wbr />&nbsp;<wbr />&nbsp;Bundle/<wbr />&nbsp;<wbr />&nbsp;autoload.php<wbr />&nbsp;<wbr />&nbsp;vendor/</li></ol><br />
実際のロジックが詰まったBundleがこのsrcディレクトリに入るようになります。<br />
<br />
ApplicationにはApplicationとして動作させるためのBundleが入ります。中にはHelloBundleというBundleがありますのでわかりやすいですね。<br />
<br />
Bundleディレクトリは空っぽです。このディレクトリは従来ののプラグインのような形で、様々なBundleを入れていくのかなと思います。<br />
<br />
autoload.phpはオートロードに関するファイルですので特に気にしないでいいでしょう。<br />
<br />
そしてvendorです。sandboxではsymfonyやDoctrineなどのコードが含まれています。Bundleではなく外部ライブラリを使いたい場合は、このディレクトリに配置します。<br />
<br />
今回だけでは説明しきれないので、helloアプリケーションのロジックが詰まっているHelloBundleだけ説明します。<br />
Applicationディレクトリの中にHelloBundleというディレクトリがありますが、これがHelloBundleです。<br />
中身は以下のようになっています。<br />
<br />
<ol class="boxcode-main no-number"><li>Bundle.php<wbr />&nbsp;<wbr />&nbsp;Controller/<wbr />&nbsp;<wbr />&nbsp;Resources/</li></ol><br />
全てのBundleに共通しているのは、BundleのディレクトリにはBundle.phpというクラスファイルが存在しています。<br />
デフォルトでは空のクラスになっていると思いますが、BundleごとのDIコンテナの設定などが必要な場合はここに処理を追加していきます。<br />
<br />
次にControllerディレクトリです。名前からも想像がつくと思いますがControllerクラスを配置します。<br />
ControllerディレクトリにはHelloController.phpがありますのでみてみます。<br />
<br />
<ol class="php-main"><li><span class="php-inlinetags">&lt;?php</span><span class="php-code"></span></li>
<li><span class="php-code"><wbr />&nbsp;</span></li>
<li><span class="php-code"></span><span class="php-identifier">namespace</span><span class="php-code"><wbr />&nbsp;</span><span class="php-identifier">Application</span><span class="php-code">\</span><span class="php-identifier">HelloBundle</span><span class="php-code">\</span><span class="php-identifier">Controller</span><span class="php-code">;</span></li>
<li><span class="php-code"><wbr />&nbsp;</span></li>
<li><span class="php-code"></span><span class="php-identifier">use</span><span class="php-code"><wbr />&nbsp;</span><span class="php-identifier">Symfony</span><span class="php-code">\</span><span class="php-identifier">Framework</span><span class="php-code">\</span><span class="php-identifier">WebBundle</span><span class="php-code">\</span><span class="php-identifier">Controller</span><span class="php-code">;</span></li>
<li><span class="php-code"><wbr />&nbsp;</span></li>
<li><span class="php-code"></span><span class="php-reserved">class</span><span class="php-code"><wbr />&nbsp;</span><span class="php-identifier">HelloController</span><span class="php-code"><wbr />&nbsp;</span><span class="php-reserved">extends</span><span class="php-code"><wbr />&nbsp;</span><span class="php-identifier">Controller</span><span class="php-code"></span></li>
<li><span class="php-code"></span><span class="php-brackets">{</span><span class="php-code"></span></li>
<li><span class="php-code"><wbr />&nbsp;<wbr />&nbsp;</span><span class="php-reserved">public</span><span class="php-code"><wbr />&nbsp;</span><span class="php-reserved">function</span><span class="php-code"><wbr />&nbsp;</span><span class="php-identifier">indexAction</span><span class="php-brackets">(</span><span class="php-var">$name</span><span class="php-brackets">)</span><span class="php-code"></span></li>
<li><span class="php-code"><wbr />&nbsp;<wbr />&nbsp;</span><span class="php-brackets">{</span><span class="php-code"></span></li>
<li><span class="php-code"><wbr />&nbsp;<wbr />&nbsp;<wbr />&nbsp;<wbr />&nbsp;</span><span class="php-reserved">return</span><span class="php-code"><wbr />&nbsp;</span><span class="php-var">$this</span><span class="php-code">-&gt;</span><span class="php-identifier">render</span><span class="php-brackets">(</span><span class="php-quotes">'</span><span class="php-string">HelloBundle:Hello:index</span><span class="php-quotes">'</span><span class="php-code">,<wbr />&nbsp;</span><span class="php-reserved">array</span><span class="php-brackets">(</span><span class="php-quotes">'</span><span class="php-string">name</span><span class="php-quotes">'</span><span class="php-code"><wbr />&nbsp;=&gt;<wbr />&nbsp;</span><span class="php-var">$name</span><span class="php-brackets">))</span><span class="php-code">;</span></li>
<li><span class="php-code"><wbr />&nbsp;<wbr />&nbsp;</span><span class="php-brackets">}</span><span class="php-code"></span></li>
<li><span class="php-code"></span><span class="php-brackets">}</span></li></ol><br />
indexAction()メソッドがアクションになります。引数で$nameを受け取っていますが、Symfony 2ではルーティングと連動して引数を受け取るようになります。<br />
<br />
Controllerはこの程度にしておいて、Resourcesを見てみましょう。configとviewディレクトリがあると思います。<br />
configにはrouting.ymlがありますので見てみましょう。<br />
<br />
<ol class="boxcode-main"><li>hello:</li><li><wbr />&nbsp;<wbr />&nbsp;pattern:<wbr />&nbsp;<wbr />&nbsp;/hello/:name</li><li><wbr />&nbsp;<wbr />&nbsp;defaults:<wbr />&nbsp;{<wbr />&nbsp;_bundle:<wbr />&nbsp;HelloBundle,<wbr />&nbsp;_controller:<wbr />&nbsp;Hello,<wbr />&nbsp;_action:<wbr />&nbsp;index<wbr />&nbsp;}</li></ol><br />
今までのものとなんとなく似ていますね。pattern属性に:nameという部分がありますが、この部分がHelloControllerのindexActionへ引数として渡されます。<br />
それ以外のものはアクションの中で $this->getRequest()->getParameter($key) としてやれば取得可能なようです。<br />
<br />
そして最後にviewです。テンプレートですね。従来のsymfonyはテンプレートが各モジュールのディレクトリに分散していました。<br />
複数のテンプレートを修正したい場合にとてもめんどうくさかったりしましたし、デザイナーさんにとってもあまりうれしくないことでした。<br />
Symfony 2からはviewディレクトリ内に全てのテンプレートファイルが入るようになります。もちろんTemplatingコンポーネントのおかげで、Twigなどのテンプレートエンジンも利用しやすくなっていますし、全体に比べると地味な変更かもしれませんが、わりとうれしい変更です。<br />
<br />
<br />
さて、結局色々話してしまいましたが、Symfony 2.0のアプリケーションのイメージは少し湧きましたか？<br />
実際にはここにDoctrineが入ってきたり、様々なBundleを実際にくみわせたりして開発することになると思います。<br />
<br />
まだまだプレビューリリース版ですから、これから様々な機能が追加されてより洗練されていくことでしょう。<br />
現状ではとても実戦投入はできそうにないですが、なんとなくSymfony 2がどのようになるかわかっていただければいいかなと思います。<br />
<br />
今後もSymfony 2の情報を追い続けようと思いますので、コマンドなどが充実してきたら実際にアプリケーションの作り方などをご紹介できればと思っています。<br />
とはいえ現状全然内部を追えていないので、まずはじっくりと調べていこうと思います。 ]]></description>
			<author>小川雄大</author>
			<category>Tech</category>
			<guid isPermaLink="true">http://blog.asial.co.jp/669</guid>
		</item>
				<item>
			<pubDate>Wed, 03 Mar 2010 22:08:37 +0900</pubDate>
			<title>サーバサイドJavaScriptの「node.js」を試してみました</title>
			<link>http://blog.asial.co.jp/668</link>
			<description><![CDATA[ こんにちは、「○○を試してみました」系のネタが大好きな中川です。<br />
<br />
今回は、PHPからちょっと離れてサーバサイドJavaScriptを触ってみました。<br />
世間では、少し前に話題になった？「node.js」を試してみます。<br />
<br />
<a href="/read_file.php?id=1034&mode=1" rel="lightbox" class="link-lightbox"><img src="http://blog.asial.co.jp/read_file.php?id=1034" /></a><br />
<br />
JavaScriptというと、クライアントのブラウザで動作して利用するのが通常ですが、node.jsはサーバサイドで利用することになります。JavaScriptエンジンにはGoogleChromeでおなじみの「V8」エンジンが使われているとのこと。<br />
<br />
さて、早速公式サイト( <a href='http://nodejs.org/'>http://nodejs.org/</a> )を頼りに進めてみます。<br />
今回の環境は、CentOS5.3を利用しています。<br />
<br />
まずは、「node.js」の本体のダウンロードからです。<br />
<br />
サイドメニューの「Download」から現時点での最新版の「2010.02.22 node-v0.1.30.tar.gz」を利用します。<br />
<br />
<ol class="boxcode-main no-number"><li>$<wbr />&nbsp;mkdir<wbr />&nbsp;node</li><li>$<wbr />&nbsp;cd<wbr />&nbsp;node</li><li>$<wbr />&nbsp;wget<wbr />&nbsp;http://nodejs.org/dist/node-v0.1.30.tar.gz</li></ol><br />
解凍して、インストール！<br />
<br />
<ol class="boxcode-main no-number"><li>$<wbr />&nbsp;tar<wbr />&nbsp;xvzf<wbr />&nbsp;node-v0.1.30.tar.gz<wbr />&nbsp;<wbr />&nbsp;<wbr />&nbsp;</li><li>$<wbr />&nbsp;cd<wbr />&nbsp;node-v0.1.30/</li><li>$<wbr />&nbsp;./configure</li><li>$<wbr />&nbsp;make</li><li>$<wbr />&nbsp;sudo<wbr />&nbsp;make<wbr />&nbsp;install	</li></ol><br />
解凍やconfigureで、なんかエラー（注意文？）が出てましたが、とりあえず、makeできたので無視しておきましょう。<br />
<br />
<br />
さて、これで本体のインストールは完了ということで、まずは「Hello World」。。。なんて、やらずにDemoのチャットアプリ( <a href='http://chat.nodejs.org/'>http://chat.nodejs.org/</a> ) のソースがあるようなので、そっちを動かすことにしましょう！<br />
<br />
<a href='http://github.com/ry/node_chat'>http://github.com/ry/node_chat</a> からgitで持ってきます。<br />
<br />
<ol class="boxcode-main no-number"><li>$<wbr />&nbsp;mkdir<wbr />&nbsp;chat_sample</li><li>$<wbr />&nbsp;cd<wbr />&nbsp;chat_sample</li><li>$<wbr />&nbsp;git<wbr />&nbsp;clone<wbr />&nbsp;git://github.com/ry/node_chat.git<wbr />&nbsp;</li><li>$<wbr />&nbsp;cd<wbr />&nbsp;node_chat</li><li>LICENSE-MIT<wbr />&nbsp;<wbr />&nbsp;README<wbr />&nbsp;<wbr />&nbsp;client.js<wbr />&nbsp;<wbr />&nbsp;fu.js<wbr />&nbsp;<wbr />&nbsp;index.html<wbr />&nbsp;<wbr />&nbsp;jquery-1.2.6.min.js<wbr />&nbsp;<wbr />&nbsp;server.js<wbr />&nbsp;<wbr />&nbsp;style.css</li></ol><br />
わずかこれだけ！<br />
<br />
さあ、実行してみます。<br />
<br />
<ol class="boxcode-main no-number"><li>$<wbr />&nbsp;node<wbr />&nbsp;server.js</li><li>Server<wbr />&nbsp;at<wbr />&nbsp;http://127.0.0.1:8001/</li></ol><br />
で、ブラウザからアクセスしてと・・・・。<br />
<br />
<a href="/read_file.php?id=1035&mode=1" rel="lightbox" class="link-lightbox"><img src="http://blog.asial.co.jp/read_file.php?id=1035" /></a><br />
<br />
おー、一発で動いた！！こんなに簡単にチャットアプリが！<br />
<br />
server.jsの中身を見てみると、わずか200行未満なのと、<br />
JavaScriptなのでクライアントサイドでいじった経験があるので、簡単に解読可能です。<br />
<br />
開発自体も現在も活発に行われているようです。( <a href='http://github.com/ry/node/commits/master'>http://github.com/ry/node/commits/master</a> )<br />
また、ネットいろいろ探してみたところ、<br />
node.js向けフレームワークの「Express」( <a href='http://github.com/visionmedia/express'>http://github.com/visionmedia/express</a> )や、<br />
MySQLドライバの「node-mysql」( <a href='http://github.com/masuidrive/node-mysql'>http://github.com/masuidrive/node-mysql</a> )など、<br />
徐々に関連モノも出てきているようですので、今後も楽しみですね！<br />
<br />
JavaScriptはもともと大好きだったのですが、<br />
さすがにサーバサイド側での利用はしたことがなくどうなんだろうというのが正直なところですが、今回試してみて非常に手軽に始められるのは分かりました！！<br />
<br />
今後もっと普及していくとうれしい限りです。 ]]></description>
			<author>中川善樹</author>
			<category>Tech</category>
			<guid isPermaLink="true">http://blog.asial.co.jp/668</guid>
		</item>
				<item>
			<pubDate>Fri, 26 Feb 2010 17:20:31 +0900</pubDate>
			<title>お初の山梨旅行</title>
			<link>http://blog.asial.co.jp/667</link>
			<description><![CDATA[ こんにちは、阿部です。<br />
<br />
おもいっきり私事ですが、先日、山梨へ旅行に行ってきました☆<br />
<br />
とりあえず、郷土料理の ほうとう <br />
<a href="/read_file.php?id=1023&mode=1" rel="lightbox" class="link-lightbox"><img src="http://blog.asial.co.jp/read_file.php?id=1023" /></a><br />
<br />
丁度出発した日から天気が崩れてしまい、富士急ハイランドはとっても残念ですが中止しました。<br />
なので、ずっと河口湖周辺をウロウロ。<br />
宿から歩いていける範囲で散策してみましたが、ほとんどの施設は既に閉店してました・・・。。17時なのに1日目終了です。。<br />
<br />
2日目。1日目に閉店してた施設めぐりです。<br />
河口湖周辺をぐる～とまわってきたのですが、一番強烈だったのが、「カチカチ山ロープウェイ」。<br />
まずはロープウェイで山の中腹まで登ります。<br />
太宰治の「かちかち山」の舞台だそうで、物語にちなんで、あちこちにタヌキやウサギの人形が置いてありました。<br />
<br />
<a href="/read_file.php?id=1025&mode=1" rel="lightbox" class="link-lightbox"><img src="http://blog.asial.co.jp/read_file.php?id=1025" /></a><br />
・・・この時期に行ったからこそとれた写真ですね！<br />
画像が小さくて見えないですが、このウサギ、鼻の頭につららができてて、ハナタレウサギでした。<br />
たぶん楽しみ方が違いますが、いろいろと楽しい場所でした。<br />
トイレにはタヌキがつるされてました。<br />
<a href="/read_file.php?id=1026&mode=1" rel="lightbox" class="link-lightbox"><img src="http://blog.asial.co.jp/read_file.php?id=1026" /></a><br />
<br />
ここでは、河口湖も富士山も一望できるそうなのですが、前日に雨、当日は雪と、悪天候のためなーんにも見えませんでした。<br />
<br />
双眼鏡も凍ってます。<br />
<a href="/read_file.php?id=1024&mode=1" rel="lightbox" class="link-lightbox"><img src="http://blog.asial.co.jp/read_file.php?id=1024" /></a><br />
<br />
<br />
山頂には徒歩で行けるようになっていますが、この日、山頂まで行ったのは自分達だけみたいです。他の観光客は途中で引き返した足跡がありました。<br />
雪が滑るので、なかなか危険な道でした。冬はやめておいた方がいいと思います。<br />
柵もなく、ヘタしたら崖からゴロンゴロンすることになります。<br />
<a href="/read_file.php?id=1032&mode=1" rel="lightbox" class="link-lightbox"><img src="http://blog.asial.co.jp/read_file.php?id=1032" /></a><a href="/read_file.php?id=1033&mode=1" rel="lightbox" class="link-lightbox"><img src="http://blog.asial.co.jp/read_file.php?id=1033" /></a><br />
<br />
<br />
もう一つ印象強かったのは、オルゴール館です。<br />
ココでは、いろいろな種類のオルゴールを観覧できます。<br />
また、弦楽四重奏の生演奏も行っていて、得した気分です。<br />
<br />
<a href="/read_file.php?id=1027&mode=1" rel="lightbox" class="link-lightbox"><img src="http://blog.asial.co.jp/read_file.php?id=1027" /></a><br />
この人形達、なんと演奏するんです。手が動くだけですけど。<br />
うしろから空気を入れることによって、いろいろな音をだせているそうな。<br />
本当に人が演奏しているような感じですごかったです。<br />
<br />
河口湖へ行くなら、冬はカチカチ山ロープウェイ、オルゴール館がオススメです☆ ]]></description>
			<author>阿部恵</author>
			<category>日常</category>
			<guid isPermaLink="true">http://blog.asial.co.jp/667</guid>
		</item>
				<item>
			<pubDate>Thu, 25 Feb 2010 18:28:29 +0900</pubDate>
			<title>OpenVPNで拠点間VPN</title>
			<link>http://blog.asial.co.jp/666</link>
			<description><![CDATA[ OpenVPNで拠点間VPN<br />
<br />
元々、個人専用のWEBサーバーを立ち上げ、ファイルサーバーのデータを外部から参照可能にしているが、<br />
単純にファイルを転送するだけならともかく、ディレクトリごとダウンロードや、一部だけ読み取ることなどは出来ないため割と不便。<br />
解決法はWebDAVとかFTPとかいろいろとある中、どうせなら自宅ネットワークに直接接続出来れば、便利じゃないかと思いVPNを張ることを計画。<br />
（NFSとかFTPとかSVNとかrsyncなどの内部用の設定なため、外部に公開したらひどいことになる通信も使える！）<br />
VPNといえば、IPSecとかPPTPなどの有名どころはありますが、割と設定が面倒で設定をしっかりしないと穴が開くこともあるので、設定が簡単な（デフォルトでもそこそこしっかりしている）OpenVPNを採用。<br />
<br />
・OpenVPNとは<br />
SSLVPNの一つで、設定がシンプル。そこそこ堅牢。IPSecなどと違い、ユーザーランドで動作するのでセキュリティホールがあった場合にも影響が少ないはず。暗号化の方式も割と自由に選択可能。<br />
<br />
以下、詳しいことはいつものとおり割愛して、具体的な設定方法。<br />
<br />
インストール<br />
<ol class="boxcode-main no-number"><li>$<wbr />&nbsp;sudo<wbr />&nbsp;apt-get<wbr />&nbsp;install<wbr />&nbsp;openvpn</li></ol><br />
証明書の作成<br />
まずは、easy-rsaをコピー<br />
<ol class="boxcode-main no-number"><li>hoge@localhost:~$<wbr />&nbsp;sudo<wbr />&nbsp;cp<wbr />&nbsp;-r<wbr />&nbsp;/usr/share/doc/openvpn/examples/easy-rsa/2.0/<wbr />&nbsp;/etc/openvpn/easy-rsa-hoge/</li></ol><br />
移動<br />
<ol class="boxcode-main no-number"><li>hoge@localhost:~$<wbr />&nbsp;cd<wbr />&nbsp;/etc/openvpn/easy-rsa-hoge/</li></ol><br />
お好みにより証明書の内容を編集(オレオレ証明書なので適当に)<br />
<ol class="boxcode-main no-number"><li>hoge@localhost:/etc/openvpn/easy-rsa-hoge$<wbr />&nbsp;vi<wbr />&nbsp;vars</li><li>##############</li><li>export<wbr />&nbsp;KEY_COUNTRY="HO"</li><li>export<wbr />&nbsp;KEY_PROVINCE="GE"</li><li>export<wbr />&nbsp;KEY_CITY="hogecity"</li><li>export<wbr />&nbsp;KEY_ORG="Hoge<wbr />&nbsp;corp"</li><li>export<wbr />&nbsp;KEY_EMAIL="me@myhost.mydomain"</li><li>##############</li></ol><br />
varsの内容を環境変数にセット<br />
<ol class="boxcode-main no-number"><li>hoge@localhost:/etc/openvpn/easy-rsa-hoge$<wbr />&nbsp;.<wbr />&nbsp;./vars</li></ol><br />
CAを作成<br />
<ol class="boxcode-main no-number"><li>hoge@localhost:/etc/openvpn/easy-rsa-hoge$<wbr />&nbsp;./build-ca</li><li>Generating<wbr />&nbsp;a<wbr />&nbsp;1024<wbr />&nbsp;bit<wbr />&nbsp;RSA<wbr />&nbsp;private<wbr />&nbsp;key</li><li>......++++++</li><li>......++++++</li><li>writing<wbr />&nbsp;new<wbr />&nbsp;private<wbr />&nbsp;key<wbr />&nbsp;to<wbr />&nbsp;'ca.key'</li><li>-----</li><li>You<wbr />&nbsp;are<wbr />&nbsp;about<wbr />&nbsp;to<wbr />&nbsp;be<wbr />&nbsp;asked<wbr />&nbsp;to<wbr />&nbsp;enter<wbr />&nbsp;information<wbr />&nbsp;that<wbr />&nbsp;will<wbr />&nbsp;be<wbr />&nbsp;incorporated</li><li>into<wbr />&nbsp;your<wbr />&nbsp;certificate<wbr />&nbsp;request.</li><li>What<wbr />&nbsp;you<wbr />&nbsp;are<wbr />&nbsp;about<wbr />&nbsp;to<wbr />&nbsp;enter<wbr />&nbsp;is<wbr />&nbsp;what<wbr />&nbsp;is<wbr />&nbsp;called<wbr />&nbsp;a<wbr />&nbsp;Distinguished<wbr />&nbsp;Name<wbr />&nbsp;or<wbr />&nbsp;a<wbr />&nbsp;DN.</li><li>There<wbr />&nbsp;are<wbr />&nbsp;quite<wbr />&nbsp;a<wbr />&nbsp;few<wbr />&nbsp;fields<wbr />&nbsp;but<wbr />&nbsp;you<wbr />&nbsp;can<wbr />&nbsp;leave<wbr />&nbsp;some<wbr />&nbsp;blank</li><li>For<wbr />&nbsp;some<wbr />&nbsp;fields<wbr />&nbsp;there<wbr />&nbsp;will<wbr />&nbsp;be<wbr />&nbsp;a<wbr />&nbsp;default<wbr />&nbsp;value,</li><li>If<wbr />&nbsp;you<wbr />&nbsp;enter<wbr />&nbsp;'.',<wbr />&nbsp;the<wbr />&nbsp;field<wbr />&nbsp;will<wbr />&nbsp;be<wbr />&nbsp;left<wbr />&nbsp;blank.</li><li>-----</li><li>Country<wbr />&nbsp;Name<wbr />&nbsp;(2<wbr />&nbsp;letter<wbr />&nbsp;code)<wbr />&nbsp;[HO]:</li><li>State<wbr />&nbsp;or<wbr />&nbsp;Province<wbr />&nbsp;Name<wbr />&nbsp;(full<wbr />&nbsp;name)<wbr />&nbsp;[GE]:</li><li>Locality<wbr />&nbsp;Name<wbr />&nbsp;(eg,<wbr />&nbsp;city)<wbr />&nbsp;[hogecity]:</li><li>Organization<wbr />&nbsp;Name<wbr />&nbsp;(eg,<wbr />&nbsp;company)<wbr />&nbsp;[Hoge<wbr />&nbsp;corp]:</li><li>Organizational<wbr />&nbsp;Unit<wbr />&nbsp;Name<wbr />&nbsp;(eg,<wbr />&nbsp;section)<wbr />&nbsp;[]:</li><li>Common<wbr />&nbsp;Name<wbr />&nbsp;(eg,<wbr />&nbsp;your<wbr />&nbsp;name<wbr />&nbsp;or<wbr />&nbsp;your<wbr />&nbsp;server's<wbr />&nbsp;hostname)<wbr />&nbsp;[Hoge<wbr />&nbsp;corp<wbr />&nbsp;CA]:</li><li>Name<wbr />&nbsp;[]:</li><li>Email<wbr />&nbsp;Address<wbr />&nbsp;[me@myhost.mydomain]:</li></ol><br />
１・サーバー側で証明書作成<br />
第一引数のサーバー名はお好みで(今回はserver)<br />
<ol class="boxcode-main no-number"><li>hoge@localhost:/etc/openvpn/easy-rsa-hoge$<wbr />&nbsp;./build-key-server<wbr />&nbsp;server</li><li>Generating<wbr />&nbsp;a<wbr />&nbsp;1024<wbr />&nbsp;bit<wbr />&nbsp;RSA<wbr />&nbsp;private<wbr />&nbsp;key</li><li>.........++++++</li><li>........++++++</li><li>writing<wbr />&nbsp;new<wbr />&nbsp;private<wbr />&nbsp;key<wbr />&nbsp;to<wbr />&nbsp;'server.key'</li><li>-----</li><li>You<wbr />&nbsp;are<wbr />&nbsp;about<wbr />&nbsp;to<wbr />&nbsp;be<wbr />&nbsp;asked<wbr />&nbsp;to<wbr />&nbsp;enter<wbr />&nbsp;information<wbr />&nbsp;that<wbr />&nbsp;will<wbr />&nbsp;be<wbr />&nbsp;incorporated</li><li>into<wbr />&nbsp;your<wbr />&nbsp;certificate<wbr />&nbsp;request.</li><li>What<wbr />&nbsp;you<wbr />&nbsp;are<wbr />&nbsp;about<wbr />&nbsp;to<wbr />&nbsp;enter<wbr />&nbsp;is<wbr />&nbsp;what<wbr />&nbsp;is<wbr />&nbsp;called<wbr />&nbsp;a<wbr />&nbsp;Distinguished<wbr />&nbsp;Name<wbr />&nbsp;or<wbr />&nbsp;a<wbr />&nbsp;DN.</li><li>There<wbr />&nbsp;are<wbr />&nbsp;quite<wbr />&nbsp;a<wbr />&nbsp;few<wbr />&nbsp;fields<wbr />&nbsp;but<wbr />&nbsp;you<wbr />&nbsp;can<wbr />&nbsp;leave<wbr />&nbsp;some<wbr />&nbsp;blank</li><li>For<wbr />&nbsp;some<wbr />&nbsp;fields<wbr />&nbsp;there<wbr />&nbsp;will<wbr />&nbsp;be<wbr />&nbsp;a<wbr />&nbsp;default<wbr />&nbsp;value,</li><li>If<wbr />&nbsp;you<wbr />&nbsp;enter<wbr />&nbsp;'.',<wbr />&nbsp;the<wbr />&nbsp;field<wbr />&nbsp;will<wbr />&nbsp;be<wbr />&nbsp;left<wbr />&nbsp;blank.</li><li>-----</li><li>Country<wbr />&nbsp;Name<wbr />&nbsp;(2<wbr />&nbsp;letter<wbr />&nbsp;code)<wbr />&nbsp;[HO]:</li><li>State<wbr />&nbsp;or<wbr />&nbsp;Province<wbr />&nbsp;Name<wbr />&nbsp;(full<wbr />&nbsp;name)<wbr />&nbsp;[GE]:</li><li>Locality<wbr />&nbsp;Name<wbr />&nbsp;(eg,<wbr />&nbsp;city)<wbr />&nbsp;[hogecity]:</li><li>Organization<wbr />&nbsp;Name<wbr />&nbsp;(eg,<wbr />&nbsp;company)<wbr />&nbsp;[Hoge<wbr />&nbsp;corp]:</li><li>Organizational<wbr />&nbsp;Unit<wbr />&nbsp;Name<wbr />&nbsp;(eg,<wbr />&nbsp;section)<wbr />&nbsp;[]:</li><li>Common<wbr />&nbsp;Name<wbr />&nbsp;(eg,<wbr />&nbsp;your<wbr />&nbsp;name<wbr />&nbsp;or<wbr />&nbsp;your<wbr />&nbsp;server's<wbr />&nbsp;hostname)<wbr />&nbsp;[server]:</li><li>Name<wbr />&nbsp;[]:</li><li>Email<wbr />&nbsp;Address<wbr />&nbsp;[me@myhost.mydomain]:</li><li></li><li>Please<wbr />&nbsp;enter<wbr />&nbsp;the<wbr />&nbsp;following<wbr />&nbsp;'extra'<wbr />&nbsp;attributes</li><li>to<wbr />&nbsp;be<wbr />&nbsp;sent<wbr />&nbsp;with<wbr />&nbsp;your<wbr />&nbsp;certificate<wbr />&nbsp;request</li><li>A<wbr />&nbsp;challenge<wbr />&nbsp;password<wbr />&nbsp;[]:</li><li>An<wbr />&nbsp;optional<wbr />&nbsp;company<wbr />&nbsp;name<wbr />&nbsp;[]:</li><li>Using<wbr />&nbsp;configuration<wbr />&nbsp;from<wbr />&nbsp;/etc/openvpn/easy-rsa-hoge/openssl.cnf</li><li>Check<wbr />&nbsp;that<wbr />&nbsp;the<wbr />&nbsp;request<wbr />&nbsp;matches<wbr />&nbsp;the<wbr />&nbsp;signature</li><li>Signature<wbr />&nbsp;ok</li><li>The<wbr />&nbsp;Subject's<wbr />&nbsp;Distinguished<wbr />&nbsp;Name<wbr />&nbsp;is<wbr />&nbsp;as<wbr />&nbsp;follows</li><li>countryName<wbr />&nbsp;<wbr />&nbsp;<wbr />&nbsp;<wbr />&nbsp;<wbr />&nbsp;<wbr />&nbsp;<wbr />&nbsp;<wbr />&nbsp;<wbr />&nbsp;<wbr />&nbsp;<wbr />&nbsp;:PRINTABLE:'HO'</li><li>stateOrProvinceName<wbr />&nbsp;<wbr />&nbsp;<wbr />&nbsp;:PRINTABLE:'GE'</li><li>localityName<wbr />&nbsp;<wbr />&nbsp;<wbr />&nbsp;<wbr />&nbsp;<wbr />&nbsp;<wbr />&nbsp;<wbr />&nbsp;<wbr />&nbsp;<wbr />&nbsp;<wbr />&nbsp;:PRINTABLE:'hogecity'</li><li>organizationName<wbr />&nbsp;<wbr />&nbsp;<wbr />&nbsp;<wbr />&nbsp;<wbr />&nbsp;<wbr />&nbsp;:PRINTABLE:'Hoge<wbr />&nbsp;corp'</li><li>commonName<wbr />&nbsp;<wbr />&nbsp;<wbr />&nbsp;<wbr />&nbsp;<wbr />&nbsp;<wbr />&nbsp;<wbr />&nbsp;<wbr />&nbsp;<wbr />&nbsp;<wbr />&nbsp;<wbr />&nbsp;<wbr />&nbsp;:PRINTABLE:'server'</li><li>emailAddress<wbr />&nbsp;<wbr />&nbsp;<wbr />&nbsp;<wbr />&nbsp;<wbr />&nbsp;<wbr />&nbsp;<wbr />&nbsp;<wbr />&nbsp;<wbr />&nbsp;<wbr />&nbsp;:IA5STRING:'me@myhost.mydomain'</li><li>Certificate<wbr />&nbsp;is<wbr />&nbsp;to<wbr />&nbsp;be<wbr />&nbsp;certified<wbr />&nbsp;until<wbr />&nbsp;Feb<wbr />&nbsp;23<wbr />&nbsp;07:32:18<wbr />&nbsp;2020<wbr />&nbsp;GMT<wbr />&nbsp;(3650<wbr />&nbsp;days)</li><li>Sign<wbr />&nbsp;the<wbr />&nbsp;certificate?<wbr />&nbsp;[y/n]:y</li><li></li><li></li><li>1<wbr />&nbsp;out<wbr />&nbsp;of<wbr />&nbsp;1<wbr />&nbsp;certificate<wbr />&nbsp;requests<wbr />&nbsp;certified,<wbr />&nbsp;commit?<wbr />&nbsp;[y/n]y</li><li>Write<wbr />&nbsp;out<wbr />&nbsp;database<wbr />&nbsp;with<wbr />&nbsp;1<wbr />&nbsp;new<wbr />&nbsp;entries</li><li>Data<wbr />&nbsp;Base<wbr />&nbsp;Updated</li></ol><br />
クライアント証明書作成<br />
クライアント名もお好みで(今回はclient)<br />
コマンドを"build-key-pass"にするとパスフレーズ付きで鍵を作成可能（ただし、起動時にパスフレーズを訊かれるため面倒）<br />
<ol class="boxcode-main no-number"><li>hoge@localhost:/etc/openvpn/easy-rsa-hoge$<wbr />&nbsp;./build-key<wbr />&nbsp;client</li><li>Generating<wbr />&nbsp;a<wbr />&nbsp;1024<wbr />&nbsp;bit<wbr />&nbsp;RSA<wbr />&nbsp;private<wbr />&nbsp;key</li><li>...................................++++++</li><li>....................++++++</li><li>writing<wbr />&nbsp;new<wbr />&nbsp;private<wbr />&nbsp;key<wbr />&nbsp;to<wbr />&nbsp;'client.key'</li><li>-----</li><li>You<wbr />&nbsp;are<wbr />&nbsp;about<wbr />&nbsp;to<wbr />&nbsp;be<wbr />&nbsp;asked<wbr />&nbsp;to<wbr />&nbsp;enter<wbr />&nbsp;information<wbr />&nbsp;that<wbr />&nbsp;will<wbr />&nbsp;be<wbr />&nbsp;incorporated</li><li>into<wbr />&nbsp;your<wbr />&nbsp;certificate<wbr />&nbsp;request.</li><li>What<wbr />&nbsp;you<wbr />&nbsp;are<wbr />&nbsp;about<wbr />&nbsp;to<wbr />&nbsp;enter<wbr />&nbsp;is<wbr />&nbsp;what<wbr />&nbsp;is<wbr />&nbsp;called<wbr />&nbsp;a<wbr />&nbsp;Distinguished<wbr />&nbsp;Name<wbr />&nbsp;or<wbr />&nbsp;a<wbr />&nbsp;DN.</li><li>There<wbr />&nbsp;are<wbr />&nbsp;quite<wbr />&nbsp;a<wbr />&nbsp;few<wbr />&nbsp;fields<wbr />&nbsp;but<wbr />&nbsp;you<wbr />&nbsp;can<wbr />&nbsp;leave<wbr />&nbsp;some<wbr />&nbsp;blank</li><li>For<wbr />&nbsp;some<wbr />&nbsp;fields<wbr />&nbsp;there<wbr />&nbsp;will<wbr />&nbsp;be<wbr />&nbsp;a<wbr />&nbsp;default<wbr />&nbsp;value,</li><li>If<wbr />&nbsp;you<wbr />&nbsp;enter<wbr />&nbsp;'.',<wbr />&nbsp;the<wbr />&nbsp;field<wbr />&nbsp;will<wbr />&nbsp;be<wbr />&nbsp;left<wbr />&nbsp;blank.</li><li>-----</li><li>Country<wbr />&nbsp;Name<wbr />&nbsp;(2<wbr />&nbsp;letter<wbr />&nbsp;code)<wbr />&nbsp;[HO]:</li><li>State<wbr />&nbsp;or<wbr />&nbsp;Province<wbr />&nbsp;Name<wbr />&nbsp;(full<wbr />&nbsp;name)<wbr />&nbsp;[GE]:</li><li>Locality<wbr />&nbsp;Name<wbr />&nbsp;(eg,<wbr />&nbsp;city)<wbr />&nbsp;[hogecity]:</li><li>Organization<wbr />&nbsp;Name<wbr />&nbsp;(eg,<wbr />&nbsp;company)<wbr />&nbsp;[Hoge<wbr />&nbsp;corp]:</li><li>Organizational<wbr />&nbsp;Unit<wbr />&nbsp;Name<wbr />&nbsp;(eg,<wbr />&nbsp;section)<wbr />&nbsp;[]:</li><li>Common<wbr />&nbsp;Name<wbr />&nbsp;(eg,<wbr />&nbsp;your<wbr />&nbsp;name<wbr />&nbsp;or<wbr />&nbsp;your<wbr />&nbsp;server's<wbr />&nbsp;hostname)<wbr />&nbsp;[client]:</li><li>Name<wbr />&nbsp;[]:</li><li>Email<wbr />&nbsp;Address<wbr />&nbsp;[me@myhost.mydomain]:</li><li></li><li>Please<wbr />&nbsp;enter<wbr />&nbsp;the<wbr />&nbsp;following<wbr />&nbsp;'extra'<wbr />&nbsp;attributes</li><li>to<wbr />&nbsp;be<wbr />&nbsp;sent<wbr />&nbsp;with<wbr />&nbsp;your<wbr />&nbsp;certificate<wbr />&nbsp;request</li><li>A<wbr />&nbsp;challenge<wbr />&nbsp;password<wbr />&nbsp;[]:</li><li>An<wbr />&nbsp;optional<wbr />&nbsp;company<wbr />&nbsp;name<wbr />&nbsp;[]:</li><li>Using<wbr />&nbsp;configuration<wbr />&nbsp;from<wbr />&nbsp;/etc/openvpn/easy-rsa-hoge/openssl.cnf</li><li>Check<wbr />&nbsp;that<wbr />&nbsp;the<wbr />&nbsp;request<wbr />&nbsp;matches<wbr />&nbsp;the<wbr />&nbsp;signature</li><li>Signature<wbr />&nbsp;ok</li><li>The<wbr />&nbsp;Subject's<wbr />&nbsp;Distinguished<wbr />&nbsp;Name<wbr />&nbsp;is<wbr />&nbsp;as<wbr />&nbsp;follows</li><li>countryName<wbr />&nbsp;<wbr />&nbsp;<wbr />&nbsp;<wbr />&nbsp;<wbr />&nbsp;<wbr />&nbsp;<wbr />&nbsp;<wbr />&nbsp;<wbr />&nbsp;<wbr />&nbsp;<wbr />&nbsp;:PRINTABLE:'HO'</li><li>stateOrProvinceName<wbr />&nbsp;<wbr />&nbsp;<wbr />&nbsp;:PRINTABLE:'GE'</li><li>localityName<wbr />&nbsp;<wbr />&nbsp;<wbr />&nbsp;<wbr />&nbsp;<wbr />&nbsp;<wbr />&nbsp;<wbr />&nbsp;<wbr />&nbsp;<wbr />&nbsp;<wbr />&nbsp;:PRINTABLE:'hogecity'</li><li>organizationName<wbr />&nbsp;<wbr />&nbsp;<wbr />&nbsp;<wbr />&nbsp;<wbr />&nbsp;<wbr />&nbsp;:PRINTABLE:'Hoge<wbr />&nbsp;corp'</li><li>commonName<wbr />&nbsp;<wbr />&nbsp;<wbr />&nbsp;<wbr />&nbsp;<wbr />&nbsp;<wbr />&nbsp;<wbr />&nbsp;<wbr />&nbsp;<wbr />&nbsp;<wbr />&nbsp;<wbr />&nbsp;<wbr />&nbsp;:PRINTABLE:'client'</li><li>emailAddress<wbr />&nbsp;<wbr />&nbsp;<wbr />&nbsp;<wbr />&nbsp;<wbr />&nbsp;<wbr />&nbsp;<wbr />&nbsp;<wbr />&nbsp;<wbr />&nbsp;<wbr />&nbsp;:IA5STRING:'me@myhost.mydomain'</li><li>Certificate<wbr />&nbsp;is<wbr />&nbsp;to<wbr />&nbsp;be<wbr />&nbsp;certified<wbr />&nbsp;until<wbr />&nbsp;Feb<wbr />&nbsp;23<wbr />&nbsp;07:35:43<wbr />&nbsp;2020<wbr />&nbsp;GMT<wbr />&nbsp;(3650<wbr />&nbsp;days)</li><li>Sign<wbr />&nbsp;the<wbr />&nbsp;certificate?<wbr />&nbsp;[y/n]:y</li><li></li><li></li><li>1<wbr />&nbsp;out<wbr />&nbsp;of<wbr />&nbsp;1<wbr />&nbsp;certificate<wbr />&nbsp;requests<wbr />&nbsp;certified,<wbr />&nbsp;commit?<wbr />&nbsp;[y/n]y</li><li>Write<wbr />&nbsp;out<wbr />&nbsp;database<wbr />&nbsp;with<wbr />&nbsp;1<wbr />&nbsp;new<wbr />&nbsp;entries</li><li>Data<wbr />&nbsp;Base<wbr />&nbsp;Updated</li></ol><br />
DH生成<br />
<ol class="boxcode-main no-number"><li>hoge@localhost:/etc/openvpn/easy-rsa-hoge$<wbr />&nbsp;./build-dh</li><li>Generating<wbr />&nbsp;DH<wbr />&nbsp;parameters,<wbr />&nbsp;1024<wbr />&nbsp;bit<wbr />&nbsp;long<wbr />&nbsp;safe<wbr />&nbsp;prime,<wbr />&nbsp;generator<wbr />&nbsp;2</li><li>This<wbr />&nbsp;is<wbr />&nbsp;going<wbr />&nbsp;to<wbr />&nbsp;take<wbr />&nbsp;a<wbr />&nbsp;long<wbr />&nbsp;time</li><li>.................+............+..............................................................................................................................................+........................\</li><li>...................................................................................................................................++*++*++*</li></ol><br />
以上で証明書生成は完了。<br />
<br />
２・サーバー側設定<br />
/etc/openvpn/server.conf<br />
<ol class="boxcode-main no-number"><li>#<wbr />&nbsp;ポート</li><li>port<wbr />&nbsp;11072</li><li></li><li>#<wbr />&nbsp;使用するプロトコル</li><li>proto<wbr />&nbsp;udp</li><li></li><li>#<wbr />&nbsp;デバイス</li><li>##<wbr />&nbsp;今回はL3トンネルなので、tunを使用</li><li>##<wbr />&nbsp;(L2の場合はtapを使用)</li><li>##<wbr />&nbsp;tun0のようにすれば、デバイスを固定出来る</li><li>dev<wbr />&nbsp;tun0</li><li></li><li>#<wbr />&nbsp;keepalive</li><li>keepalive<wbr />&nbsp;10<wbr />&nbsp;120</li><li></li><li>#<wbr />&nbsp;実行中はnobodyとして動作</li><li>user<wbr />&nbsp;nobody</li><li>group<wbr />&nbsp;nogroup</li><li></li><li>#<wbr />&nbsp;証明書関係</li><li>ca<wbr />&nbsp;/etc/openvpn/easy-rsa-hoge/keys/ca.crt</li><li>cert<wbr />&nbsp;/etc/openvpn/easy-rsa-hoge/keys/server.crt</li><li>key<wbr />&nbsp;/etc/openvpn/easy-rsa-hoge/keys/server.key</li><li>dh<wbr />&nbsp;/etc/openvpn/easy-rsa-hoge/keys/dh1024.pem</li><li></li><li>#<wbr />&nbsp;サーバーとして設定</li><li>tls-server</li><li></li><li>#<wbr />&nbsp;server<wbr />&nbsp;ネットワーク<wbr />&nbsp;ネットマスク</li><li>##<wbr />&nbsp;このネットワークの範囲内で自動的にIPを割り振る</li><li>server<wbr />&nbsp;192.168.4.0<wbr />&nbsp;255.255.255.0</li><li></li><li>#<wbr />&nbsp;割り振ったIPの記録先（証明書ベースでIPを管理）</li><li>ifconfig-pool-persist<wbr />&nbsp;/etc/openvpn/hoge-persist</li><li>#<wbr />&nbsp;クライアントに送るコマンド</li><li>#<wbr />&nbsp;192.168.1.100/32へ行くにはこのネットワークを通す設定</li><li>push<wbr />&nbsp;"route<wbr />&nbsp;192.168.1.100<wbr />&nbsp;255.255.255.255"</li><li></li><li>persist-key</li><li>persist-tun</li><li></li><li>#<wbr />&nbsp;ログの出力先</li><li>##<wbr />&nbsp;設定しないと標準出力に表示</li><li>log<wbr />&nbsp;/var/log/openvpn-hoge.log</li><li>log-append<wbr />&nbsp;/var/log/openvpn-hoge.log</li><li></li><li>#<wbr />&nbsp;ログレベル</li><li>verb<wbr />&nbsp;3</li><li></li><li>#<wbr />&nbsp;MTUの設定</li><li>fragment<wbr />&nbsp;1200</li><li>mssfix</li><li></li></ol>こんな感じで設定。<br />
<br />
*.confとなっていれば起動時に自動で読み込まれるため、ポート・デバイスをそれぞれ設定すれば、複数のサーバーを起動可能。<br />
<br />
３・クライアント設定<br />
/etc/openvpn/client.conf<br />
<ol class="boxcode-main no-number"><li>#<wbr />&nbsp;クライアントとして設定</li><li>tls-client</li><li></li><li>#<wbr />&nbsp;使用するプロトコル</li><li>proto<wbr />&nbsp;udp</li><li></li><li>#<wbr />&nbsp;デバイス</li><li>dev<wbr />&nbsp;tun</li><li></li><li>#<wbr />&nbsp;サーバーのアドレスとポート</li><li>remote<wbr />&nbsp;hoge.example.com<wbr />&nbsp;11072</li><li></li><li>#<wbr />&nbsp;証明書関係</li><li>ca<wbr />&nbsp;/etc/openvpn/keys/ca.crt</li><li>cert<wbr />&nbsp;/etc/openvpn/keys/client.crt</li><li>key<wbr />&nbsp;/etc/openvpn/keys/client.key</li><li></li><li>user<wbr />&nbsp;nobody</li><li>group<wbr />&nbsp;nogroup</li><li></li><li>#<wbr />&nbsp;pushで送られた設定を受け取る</li><li>pull</li><li>#<wbr />&nbsp;IPを受け取る</li><li>float</li><li></li><li>persist-key</li><li>persist-tun</li><li>resolv-retry<wbr />&nbsp;infinite</li><li>nobind</li><li></li><li>#<wbr />&nbsp;ログの詳細レベルの指定</li><li>verb<wbr />&nbsp;3</li><li></li><li>log<wbr />&nbsp;/var/log/openvpn-tun.log</li><li>log-append<wbr />&nbsp;/var/log/openvpn-tun.log</li><li></li><li>keepalive<wbr />&nbsp;10<wbr />&nbsp;120</li><li></li><li>replay-window<wbr />&nbsp;128</li><li>fragment<wbr />&nbsp;1200</li><li>mssfix</li><li></li></ol><br />
こちらも、*.confとなっていれば起動時に自動で読み込まれるため、複数のサーバーへ接続も可能。<br />
<br />
下記ファイルを安全な方法でクライアントにコピーすれば完了。<br />
<ol class="boxcode-main no-number"><li>/etc/openvpn/easy-rsa-hoge/keys/ca.crt</li><li>/etc/openvpn/easy-rsa-hoge/keys/client.crt</li><li>/etc/openvpn/easy-rsa-hoge/keys/client.key</li></ol><br />
４・起動<br />
<br />
起動確認<br />
サーバー側<br />
<ol class="boxcode-main no-number"><li>$<wbr />&nbsp;sudo<wbr />&nbsp;openvpn<wbr />&nbsp;--config<wbr />&nbsp;/etc/openvpn/server.conf</li></ol><br />
クライアント側<br />
<ol class="boxcode-main no-number"><li>$<wbr />&nbsp;sudo<wbr />&nbsp;openvpn<wbr />&nbsp;--config<wbr />&nbsp;/etc/openvpn/client.conf</li></ol><br />
設定ファイルのlog,log-append行をコメントアウトしないとログが標準出力に出ないので注意。<br />
<br />
正常に通信出来たら一度終了し、<br />
<ol class="boxcode-main no-number"><li>$<wbr />&nbsp;sudo<wbr />&nbsp;/etc/init.d/openvpn<wbr />&nbsp;restart</li></ol>で起動すればOK<br />
<br />
<br />
５・MTUとかfragmentとか<br />
<br />
私の場合は、クライアントからサーバーまでとりあえず、pingはOK、SSHでも正常に反応するが、NFSでアクセスすると突然フリーズ。<br />
前にPPPoEでもハマったことがあったため、多分MTUが問題じゃないかと思いググってみるとfragmentとかmssfixというオプションに行き着く。<br />
fragmentは指定した長さ以上のらパケットが来たら分割するオプションらしい。<br />
fragmentの値を適当に小さくすれば、フリーズは完治。パフォーマンスは取り合えず動いているので放置。<br />
<br />
ddの結果はこんな感じになったため、そこそこ速度は出る模様。<br />
102400+0 records in<br />
102400+0 records out<br />
104857600 bytes (105 MB) copied, 61.1367 s, 1.7 MB/s ]]></description>
			<author>門脇優児</author>
			<category>Tech</category>
			<guid isPermaLink="true">http://blog.asial.co.jp/666</guid>
		</item>
				<item>
			<pubDate>Wed, 24 Feb 2010 22:08:49 +0900</pubDate>
			<title>OracleでのLIMITの記述あれこれ</title>
			<link>http://blog.asial.co.jp/665</link>
			<description><![CDATA[ こんにちは。Oracle挑戦中の松田です。<br />
今までまったく触ったことのなかったOracleに初めて触れ、頭が混乱中なので備忘録がわりにブログに書き留めておきます。<br />
<br />
特に悩んだのがLIMIT関連。<br />
何故かOracleってLIMITが無いんですね。LIMITに慣れていると、なぜ存在していないのかが不思議でしょうがありません。ほんとどうしてなんでしょ？<br />
<br />
<strong>・memberテーブルから LIMIT 10 で結果取得</strong><br />
<ol class="boxcode-main no-number"><li>SELECT<wbr />&nbsp;</li><li><wbr />&nbsp;<wbr />&nbsp;*<wbr />&nbsp;</li><li>FROM<wbr />&nbsp;</li><li><wbr />&nbsp;<wbr />&nbsp;member<wbr />&nbsp;</li><li>WHERE<wbr />&nbsp;</li><li><wbr />&nbsp;<wbr />&nbsp;ROWNUM<wbr />&nbsp;<=<wbr />&nbsp;10</li></ol>ROWNUM ･･･ 抽出した結果セットに勝手に付けられるレコード番号<br />
基本はこれを使って結果セットの切り分けをするらしい。<br />
<br />
<br />
<strong>・memberテーブルから LIMIT 10, OFFSET 5 で結果取得</strong><br />
<ol class="boxcode-main no-number"><li>SELECT<wbr />&nbsp;</li><li><wbr />&nbsp;<wbr />&nbsp;*</li><li>FROM</li><li><wbr />&nbsp;<wbr />&nbsp;(</li><li><wbr />&nbsp;<wbr />&nbsp;<wbr />&nbsp;<wbr />&nbsp;SELECT<wbr />&nbsp;</li><li><wbr />&nbsp;<wbr />&nbsp;<wbr />&nbsp;<wbr />&nbsp;<wbr />&nbsp;<wbr />&nbsp;id,<wbr />&nbsp;category,<wbr />&nbsp;age,<wbr />&nbsp;ROWNUM<wbr />&nbsp;line</li><li><wbr />&nbsp;<wbr />&nbsp;<wbr />&nbsp;<wbr />&nbsp;FROM</li><li><wbr />&nbsp;<wbr />&nbsp;<wbr />&nbsp;<wbr />&nbsp;<wbr />&nbsp;<wbr />&nbsp;member</li><li><wbr />&nbsp;<wbr />&nbsp;)</li><li>WHERE</li><li><wbr />&nbsp;<wbr />&nbsp;line<wbr />&nbsp;BETWEEN<wbr />&nbsp;6<wbr />&nbsp;AND<wbr />&nbsp;16</li></ol>サブクエリ内でいったんROWNUMを付けておき、それをBETWEENで範囲指定して取得する。<br />
<br />
<br />
<strong>・memberテーブルから、グループ（category）ごとに最も年齢（age）の高い人をそれぞれ取得</strong><br />
<ol class="boxcode-main no-number"><li>SELECT<wbr />&nbsp;</li><li><wbr />&nbsp;<wbr />&nbsp;*<wbr />&nbsp;</li><li>FROM<wbr />&nbsp;</li><li><wbr />&nbsp;<wbr />&nbsp;(</li><li><wbr />&nbsp;<wbr />&nbsp;<wbr />&nbsp;<wbr />&nbsp;SELECT<wbr />&nbsp;</li><li><wbr />&nbsp;<wbr />&nbsp;<wbr />&nbsp;<wbr />&nbsp;<wbr />&nbsp;<wbr />&nbsp;id,<wbr />&nbsp;age,<wbr />&nbsp;category,</li><li><wbr />&nbsp;<wbr />&nbsp;<wbr />&nbsp;<wbr />&nbsp;<wbr />&nbsp;<wbr />&nbsp;rank()<wbr />&nbsp;OVER<wbr />&nbsp;(PARTITION<wbr />&nbsp;BY<wbr />&nbsp;category<wbr />&nbsp;ORDER<wbr />&nbsp;BY<wbr />&nbsp;age<wbr />&nbsp;DESC)<wbr />&nbsp;as<wbr />&nbsp;rank<wbr />&nbsp;</li><li><wbr />&nbsp;<wbr />&nbsp;<wbr />&nbsp;<wbr />&nbsp;FROM<wbr />&nbsp;</li><li><wbr />&nbsp;<wbr />&nbsp;<wbr />&nbsp;<wbr />&nbsp;<wbr />&nbsp;<wbr />&nbsp;member</li><li><wbr />&nbsp;<wbr />&nbsp;)<wbr />&nbsp;rn<wbr />&nbsp;</li><li>WHERE<wbr />&nbsp;</li><li><wbr />&nbsp;<wbr />&nbsp;rn.rank<wbr />&nbsp;=<wbr />&nbsp;1</li></ol>rank() over ～ の行で各カテゴリごとにランキングの数値を付ける。<br />
後にそのランキングが1位のものを rn.rank = 1 で指定して取ってくる。<br />
<br />
<br />
とりあえずこれだけ。<br />
もうここまででものすごく頭が痛いです。<br />
正直まったくピンと来てませんが、最後の例はMySQLだと記述方法がパッっと思いつかないので覚えられれば便利なのかも。<br />
<br />
実際に仕事で使ったテーブルを架空のテーブルに置き換えて記述しなおしているので、実際動くかどうかは若干不安です。 ]]></description>
			<author>松田惇</author>
			<category>Tech</category>
			<guid isPermaLink="true">http://blog.asial.co.jp/665</guid>
		</item>
				<item>
			<pubDate>Thu, 18 Feb 2010 22:15:01 +0900</pubDate>
			<title>symfony DoctrineのTIPS その２</title>
			<link>http://blog.asial.co.jp/664</link>
			<description><![CDATA[ こんばんは。牧野です。<br />
<br />
最近、会社で使っているPCも自分用のノートPCもハードディスク容量が少ないせいか、重く感じるようになっていました。<br />
そんな時に発表されたsonyの新しいVAIO Z。シミュレータで出てきた価格にびっくりしつつも、心ひかれています。。。<br />
<br />
さて、今日はsymfonyと使うDoctrineのTIPSその2です。ここのところ、またsymfonyを触る機会が増えていました。<br />
<br />
１．生SQLを使う<br />
schema.ymlをちゃんと書けばDQLでたいていのことはできるのですが、そのままSQLを実行してデータを取りたい時にどうぞ。<br />
Doctrine_Connectionオブジェクトがあれば、とりあえず何でもできます。<br />
<ol class="boxcode-main no-number"><li>$con<wbr />&nbsp;=<wbr />&nbsp;Doctrine::getTable(適当なテーブル)->getConnection();</li><li>$con<wbr />&nbsp;=<wbr />&nbsp;Doctrine_Manager::getInstance()->getConnection(コネクション名);</li><li>$sql<wbr />&nbsp;=<wbr />&nbsp;"select<wbr />&nbsp;*<wbr />&nbsp;from<wbr />&nbsp;hogehgoe";</li><li>$results<wbr />&nbsp;=<wbr />&nbsp;$con->fetchAll($sql);</li></ol>複数のデータを取得するfetchAll(=fetchAssoc)メソッド、一つのデータを連想配列で取得するfetchRowメソッドあたりが便利だと思います。<br />
<br />
<br />
２．データ更新時の注意<br />
Doctrineは関連するデータを簡単に引っ張ってこられるところが便利なのですが、データ更新をする際には気をつけたいことがあります。<br />
あるモデルオブジェクトのデータ変更内容を確定させる前に、同じモデルオブジェクトを取得するようなことをすると、確定前のデータ変更内容はリセットされます。<br />
<br />
具体例な例を見てみましょう。<br />
<br />
config/schema.yml<br />
<br />
<ol class="boxcode-main no-number"><li>DvdSeries:</li><li><wbr />&nbsp;<wbr />&nbsp;tableName:<wbr />&nbsp;dvd_series</li><li><wbr />&nbsp;<wbr />&nbsp;columns:</li><li><wbr />&nbsp;<wbr />&nbsp;<wbr />&nbsp;<wbr />&nbsp;id:</li><li><wbr />&nbsp;<wbr />&nbsp;<wbr />&nbsp;<wbr />&nbsp;<wbr />&nbsp;<wbr />&nbsp;type:<wbr />&nbsp;integer(4)</li><li><wbr />&nbsp;<wbr />&nbsp;<wbr />&nbsp;<wbr />&nbsp;<wbr />&nbsp;<wbr />&nbsp;primary:<wbr />&nbsp;true</li><li><wbr />&nbsp;<wbr />&nbsp;<wbr />&nbsp;<wbr />&nbsp;<wbr />&nbsp;<wbr />&nbsp;autoincrement:<wbr />&nbsp;true</li><li><wbr />&nbsp;<wbr />&nbsp;<wbr />&nbsp;<wbr />&nbsp;series_title:</li><li><wbr />&nbsp;<wbr />&nbsp;<wbr />&nbsp;<wbr />&nbsp;<wbr />&nbsp;<wbr />&nbsp;type:<wbr />&nbsp;string(255)</li><li><wbr />&nbsp;<wbr />&nbsp;<wbr />&nbsp;<wbr />&nbsp;<wbr />&nbsp;<wbr />&nbsp;notnull:<wbr />&nbsp;true</li><li></li><li>DvdPackage:</li><li><wbr />&nbsp;<wbr />&nbsp;tableName:<wbr />&nbsp;dvd_package</li><li><wbr />&nbsp;<wbr />&nbsp;columns:</li><li><wbr />&nbsp;<wbr />&nbsp;<wbr />&nbsp;<wbr />&nbsp;id:</li><li><wbr />&nbsp;<wbr />&nbsp;<wbr />&nbsp;<wbr />&nbsp;<wbr />&nbsp;<wbr />&nbsp;type:<wbr />&nbsp;integer(4)</li><li><wbr />&nbsp;<wbr />&nbsp;<wbr />&nbsp;<wbr />&nbsp;<wbr />&nbsp;<wbr />&nbsp;primary:<wbr />&nbsp;true</li><li><wbr />&nbsp;<wbr />&nbsp;<wbr />&nbsp;<wbr />&nbsp;<wbr />&nbsp;<wbr />&nbsp;autoincrement:<wbr />&nbsp;true</li><li><wbr />&nbsp;<wbr />&nbsp;<wbr />&nbsp;<wbr />&nbsp;dvd_series_id:</li><li><wbr />&nbsp;<wbr />&nbsp;<wbr />&nbsp;<wbr />&nbsp;<wbr />&nbsp;<wbr />&nbsp;type:<wbr />&nbsp;integer(4)</li><li><wbr />&nbsp;<wbr />&nbsp;<wbr />&nbsp;<wbr />&nbsp;number:</li><li><wbr />&nbsp;<wbr />&nbsp;<wbr />&nbsp;<wbr />&nbsp;<wbr />&nbsp;<wbr />&nbsp;type:<wbr />&nbsp;integer(4)</li><li><wbr />&nbsp;<wbr />&nbsp;<wbr />&nbsp;<wbr />&nbsp;package_title:</li><li><wbr />&nbsp;<wbr />&nbsp;<wbr />&nbsp;<wbr />&nbsp;<wbr />&nbsp;<wbr />&nbsp;type:<wbr />&nbsp;string(255)</li><li><wbr />&nbsp;<wbr />&nbsp;<wbr />&nbsp;<wbr />&nbsp;price:</li><li><wbr />&nbsp;<wbr />&nbsp;<wbr />&nbsp;<wbr />&nbsp;<wbr />&nbsp;<wbr />&nbsp;type:<wbr />&nbsp;integer(11)</li><li><wbr />&nbsp;<wbr />&nbsp;<wbr />&nbsp;<wbr />&nbsp;release_date:</li><li><wbr />&nbsp;<wbr />&nbsp;<wbr />&nbsp;<wbr />&nbsp;<wbr />&nbsp;<wbr />&nbsp;type:<wbr />&nbsp;date</li><li><wbr />&nbsp;<wbr />&nbsp;relations:</li><li><wbr />&nbsp;<wbr />&nbsp;<wbr />&nbsp;<wbr />&nbsp;DvdSeries:</li><li><wbr />&nbsp;<wbr />&nbsp;<wbr />&nbsp;<wbr />&nbsp;<wbr />&nbsp;<wbr />&nbsp;local:<wbr />&nbsp;dvd_series_id</li><li><wbr />&nbsp;<wbr />&nbsp;<wbr />&nbsp;<wbr />&nbsp;<wbr />&nbsp;<wbr />&nbsp;foreign:<wbr />&nbsp;id</li><li><wbr />&nbsp;<wbr />&nbsp;<wbr />&nbsp;<wbr />&nbsp;<wbr />&nbsp;<wbr />&nbsp;class:<wbr />&nbsp;DvdSeries</li><li><wbr />&nbsp;<wbr />&nbsp;<wbr />&nbsp;<wbr />&nbsp;<wbr />&nbsp;<wbr />&nbsp;foreignAlias:<wbr />&nbsp;DvdPackages</li><li></li></ol><br />
<br />
DBの中身<br />
<ol class="boxcode-main no-number"><li>mysql><wbr />&nbsp;select<wbr />&nbsp;*<wbr />&nbsp;from<wbr />&nbsp;dvd_series;</li><li>+----+-----------------+</li><li>|<wbr />&nbsp;id<wbr />&nbsp;|<wbr />&nbsp;series_title<wbr />&nbsp;<wbr />&nbsp;<wbr />&nbsp;<wbr />&nbsp;|</li><li>+----+-----------------+</li><li>|<wbr />&nbsp;<wbr />&nbsp;1<wbr />&nbsp;|<wbr />&nbsp;シーズン１<wbr />&nbsp;<wbr />&nbsp;<wbr />&nbsp;<wbr />&nbsp;<wbr />&nbsp;<wbr />&nbsp;|<wbr />&nbsp;</li><li>+----+-----------------+</li><li>1<wbr />&nbsp;row<wbr />&nbsp;in<wbr />&nbsp;set<wbr />&nbsp;(0.00<wbr />&nbsp;sec)</li><li></li><li>mysql><wbr />&nbsp;select<wbr />&nbsp;*<wbr />&nbsp;from<wbr />&nbsp;dvd_package\G</li><li>***************************<wbr />&nbsp;1.<wbr />&nbsp;row<wbr />&nbsp;***************************</li><li><wbr />&nbsp;<wbr />&nbsp;<wbr />&nbsp;<wbr />&nbsp;<wbr />&nbsp;<wbr />&nbsp;<wbr />&nbsp;<wbr />&nbsp;<wbr />&nbsp;<wbr />&nbsp;<wbr />&nbsp;id:<wbr />&nbsp;1</li><li>dvd_series_id:<wbr />&nbsp;1</li><li><wbr />&nbsp;<wbr />&nbsp;<wbr />&nbsp;<wbr />&nbsp;<wbr />&nbsp;<wbr />&nbsp;<wbr />&nbsp;number:<wbr />&nbsp;1</li><li>package_title:<wbr />&nbsp;テストタイトルその1</li><li><wbr />&nbsp;<wbr />&nbsp;<wbr />&nbsp;<wbr />&nbsp;<wbr />&nbsp;<wbr />&nbsp;<wbr />&nbsp;<wbr />&nbsp;price:<wbr />&nbsp;3000</li><li><wbr />&nbsp;release_date:<wbr />&nbsp;2010-03-01</li><li>***************************<wbr />&nbsp;2.<wbr />&nbsp;row<wbr />&nbsp;***************************</li><li><wbr />&nbsp;<wbr />&nbsp;<wbr />&nbsp;<wbr />&nbsp;<wbr />&nbsp;<wbr />&nbsp;<wbr />&nbsp;<wbr />&nbsp;<wbr />&nbsp;<wbr />&nbsp;<wbr />&nbsp;id:<wbr />&nbsp;2</li><li>dvd_series_id:<wbr />&nbsp;1</li><li><wbr />&nbsp;<wbr />&nbsp;<wbr />&nbsp;<wbr />&nbsp;<wbr />&nbsp;<wbr />&nbsp;<wbr />&nbsp;number:<wbr />&nbsp;2</li><li>package_title:<wbr />&nbsp;テストタイトルその2</li><li><wbr />&nbsp;<wbr />&nbsp;<wbr />&nbsp;<wbr />&nbsp;<wbr />&nbsp;<wbr />&nbsp;<wbr />&nbsp;<wbr />&nbsp;price:<wbr />&nbsp;4000</li><li><wbr />&nbsp;release_date:<wbr />&nbsp;2010-04-02</li><li>***************************<wbr />&nbsp;3.<wbr />&nbsp;row<wbr />&nbsp;***************************</li><li><wbr />&nbsp;<wbr />&nbsp;<wbr />&nbsp;<wbr />&nbsp;<wbr />&nbsp;<wbr />&nbsp;<wbr />&nbsp;<wbr />&nbsp;<wbr />&nbsp;<wbr />&nbsp;<wbr />&nbsp;id:<wbr />&nbsp;3</li><li>dvd_series_id:<wbr />&nbsp;1</li><li><wbr />&nbsp;<wbr />&nbsp;<wbr />&nbsp;<wbr />&nbsp;<wbr />&nbsp;<wbr />&nbsp;<wbr />&nbsp;number:<wbr />&nbsp;3</li><li>package_title:<wbr />&nbsp;テストタイトルその3</li><li><wbr />&nbsp;<wbr />&nbsp;<wbr />&nbsp;<wbr />&nbsp;<wbr />&nbsp;<wbr />&nbsp;<wbr />&nbsp;<wbr />&nbsp;price:<wbr />&nbsp;4000</li><li><wbr />&nbsp;release_date:<wbr />&nbsp;2010-05-03</li><li>***************************<wbr />&nbsp;4.<wbr />&nbsp;row<wbr />&nbsp;***************************</li><li><wbr />&nbsp;<wbr />&nbsp;<wbr />&nbsp;<wbr />&nbsp;<wbr />&nbsp;<wbr />&nbsp;<wbr />&nbsp;<wbr />&nbsp;<wbr />&nbsp;<wbr />&nbsp;<wbr />&nbsp;id:<wbr />&nbsp;4</li><li>dvd_series_id:<wbr />&nbsp;NULL</li><li><wbr />&nbsp;<wbr />&nbsp;<wbr />&nbsp;<wbr />&nbsp;<wbr />&nbsp;<wbr />&nbsp;<wbr />&nbsp;number:<wbr />&nbsp;NULL</li><li>package_title:<wbr />&nbsp;テストタイトル</li><li><wbr />&nbsp;<wbr />&nbsp;<wbr />&nbsp;<wbr />&nbsp;<wbr />&nbsp;<wbr />&nbsp;<wbr />&nbsp;<wbr />&nbsp;price:<wbr />&nbsp;3000</li><li><wbr />&nbsp;release_date:<wbr />&nbsp;2010-06-04</li><li>4<wbr />&nbsp;rows<wbr />&nbsp;in<wbr />&nbsp;set<wbr />&nbsp;(0.00<wbr />&nbsp;sec)</li></ol><br />
lib/model/doctrine/DvdPackage.class.php<br />
<ol class="php-main"><li><span class="php-code">class<wbr />&nbsp;DvdPackage<wbr />&nbsp;extends<wbr />&nbsp;BaseDvdPackage</span></li>
<li><span class="php-code">{</span></li>
<li><span class="php-code"><wbr />&nbsp;<wbr />&nbsp;/**</span></li>
<li><span class="php-code"><wbr />&nbsp;<wbr />&nbsp;<wbr />&nbsp;*<wbr />&nbsp;同一シリーズのDVD発売日をまとめてずらす。</span></li>
<li><span class="php-code"><wbr />&nbsp;<wbr />&nbsp;<wbr />&nbsp;*</span></li>
<li><span class="php-code"><wbr />&nbsp;<wbr />&nbsp;<wbr />&nbsp;*/</span></li>
<li><span class="php-code"><wbr />&nbsp;<wbr />&nbsp;public<wbr />&nbsp;function<wbr />&nbsp;changeAllSeriesReleaseDate($date_string)</span></li>
<li><span class="php-code"><wbr />&nbsp;<wbr />&nbsp;{</span></li>
<li><span class="php-code"><wbr />&nbsp;<wbr />&nbsp;<wbr />&nbsp;<wbr />&nbsp;$old_timestamp<wbr />&nbsp;=<wbr />&nbsp;strtotime($this-&gt;release_date);</span></li>
<li><span class="php-code"><wbr />&nbsp;<wbr />&nbsp;<wbr />&nbsp;<wbr />&nbsp;$new_timestamp<wbr />&nbsp;=<wbr />&nbsp;strtotime($date_string);</span></li>
<li><span class="php-code"><wbr />&nbsp;<wbr />&nbsp;<wbr />&nbsp;<wbr />&nbsp;$today_timestamp<wbr />&nbsp;=<wbr />&nbsp;strtotime(date('Y-m-d'));</span></li>
<li><span class="php-code"><wbr />&nbsp;</span></li>
<li><span class="php-code"><wbr />&nbsp;<wbr />&nbsp;<wbr />&nbsp;<wbr />&nbsp;$this-&gt;release_date<wbr />&nbsp;=<wbr />&nbsp;$date_string;</span></li>
<li><span class="php-code"><wbr />&nbsp;</span></li>
<li><span class="php-code"><wbr />&nbsp;<wbr />&nbsp;//変更前、または変更後の発売日が以前の場合は、他のDVDの発売日は変更しない。</span></li>
<li><span class="php-code"><wbr />&nbsp;<wbr />&nbsp;<wbr />&nbsp;<wbr />&nbsp;if<wbr />&nbsp;($today_timestamp<wbr />&nbsp;&gt;<wbr />&nbsp;$old_timestamp<wbr />&nbsp;||<wbr />&nbsp;$today_timestamp<wbr />&nbsp;&gt;<wbr />&nbsp;$new_timestamp)<wbr />&nbsp;{</span></li>
<li><span class="php-code"><wbr />&nbsp;<wbr />&nbsp;<wbr />&nbsp;<wbr />&nbsp;<wbr />&nbsp;<wbr />&nbsp;return<wbr />&nbsp;$this-&gt;save();</span></li>
<li><span class="php-code"><wbr />&nbsp;<wbr />&nbsp;<wbr />&nbsp;<wbr />&nbsp;}</span></li>
<li><span class="php-code"><wbr />&nbsp;</span></li>
<li><span class="php-code"><wbr />&nbsp;<wbr />&nbsp;<wbr />&nbsp;<wbr />&nbsp;$change_timestamp<wbr />&nbsp;=<wbr />&nbsp;$new_timestamp<wbr />&nbsp;-<wbr />&nbsp;$old_timestamp;</span></li>
<li><span class="php-code"><wbr />&nbsp;</span></li>
<li><span class="php-code"><wbr />&nbsp;<wbr />&nbsp;<wbr />&nbsp;<wbr />&nbsp;if<wbr />&nbsp;($this-&gt;DvdSeries)<wbr />&nbsp;{</span></li>
<li><span class="php-code"><wbr />&nbsp;<wbr />&nbsp;<wbr />&nbsp;<wbr />&nbsp;<wbr />&nbsp;<wbr />&nbsp;foreach<wbr />&nbsp;($this-&gt;DvdSeries-&gt;DvdPackages<wbr />&nbsp;as<wbr />&nbsp;$key<wbr />&nbsp;=&gt;<wbr />&nbsp;$dvd)<wbr />&nbsp;{</span></li>
<li><span class="php-code"><wbr />&nbsp;<wbr />&nbsp;<wbr />&nbsp;<wbr />&nbsp;<wbr />&nbsp;<wbr />&nbsp;<wbr />&nbsp;<wbr />&nbsp;if<wbr />&nbsp;($dvd-&gt;id<wbr />&nbsp;==<wbr />&nbsp;$this-&gt;id)<wbr />&nbsp;{</span></li>
<li><span class="php-code"><wbr />&nbsp;<wbr />&nbsp;<wbr />&nbsp;<wbr />&nbsp;<wbr />&nbsp;<wbr />&nbsp;<wbr />&nbsp;<wbr />&nbsp;<wbr />&nbsp;<wbr />&nbsp;continue;</span></li>
<li><span class="php-code"><wbr />&nbsp;<wbr />&nbsp;<wbr />&nbsp;<wbr />&nbsp;<wbr />&nbsp;<wbr />&nbsp;<wbr />&nbsp;<wbr />&nbsp;}</span></li>
<li><span class="php-code"><wbr />&nbsp;<wbr />&nbsp;<wbr />&nbsp;<wbr />&nbsp;<wbr />&nbsp;<wbr />&nbsp;<wbr />&nbsp;<wbr />&nbsp;$this-&gt;DvdSeries-&gt;DvdPackages[$key]-&gt;release_date<wbr />&nbsp;=<wbr />&nbsp;date('Y-m-d',<wbr />&nbsp;strtotime($dvd-&gt;release_date)<wbr />&nbsp;+<wbr />&nbsp;$change_timestamp);</span></li>
<li><span class="php-code"><wbr />&nbsp;<wbr />&nbsp;<wbr />&nbsp;<wbr />&nbsp;<wbr />&nbsp;<wbr />&nbsp;}</span></li>
<li><span class="php-code"><wbr />&nbsp;<wbr />&nbsp;<wbr />&nbsp;<wbr />&nbsp;}</span></li>
<li><span class="php-code"><wbr />&nbsp;<wbr />&nbsp;<wbr />&nbsp;<wbr />&nbsp;return<wbr />&nbsp;$this-&gt;save();</span></li>
<li><span class="php-code"><wbr />&nbsp;<wbr />&nbsp;}</span></li>
<li><span class="php-code">}</span></li></ol><br />
テスト用のアクションクラス<br />
<ol class="php-main"><li><span class="php-code">class<wbr />&nbsp;testActions<wbr />&nbsp;extends<wbr />&nbsp;sfActions{</span></li>
<li><span class="php-code"><wbr />&nbsp;<wbr />&nbsp;public<wbr />&nbsp;function<wbr />&nbsp;executeIndex(sfWebRequest<wbr />&nbsp;$request)</span></li>
<li><span class="php-code"><wbr />&nbsp;<wbr />&nbsp;{</span></li>
<li><span class="php-code"><wbr />&nbsp;<wbr />&nbsp;<wbr />&nbsp;<wbr />&nbsp;echo<wbr />&nbsp;&quot;&lt;pre&gt;&quot;;</span></li>
<li><span class="php-code"><wbr />&nbsp;<wbr />&nbsp;<wbr />&nbsp;<wbr />&nbsp;$con<wbr />&nbsp;=<wbr />&nbsp;Doctrine::getTable('DvdPackage')-&gt;getConnection();</span></li>
<li><span class="php-code"><wbr />&nbsp;</span></li>
<li><span class="php-code"><wbr />&nbsp;<wbr />&nbsp;<wbr />&nbsp;<wbr />&nbsp;//dvd_seriesをもつデータ</span></li>
<li><span class="php-code"><wbr />&nbsp;<wbr />&nbsp;<wbr />&nbsp;<wbr />&nbsp;$test_dvd<wbr />&nbsp;=<wbr />&nbsp;Doctrine::getTable('DvdPackage')-&gt;find(1);</span></li>
<li><span class="php-code"><wbr />&nbsp;</span></li>
<li><span class="php-code"><wbr />&nbsp;<wbr />&nbsp;<wbr />&nbsp;<wbr />&nbsp;var_dump($test_dvd-&gt;toArray());</span></li>
<li><span class="php-code"><wbr />&nbsp;</span></li>
<li><span class="php-code"><wbr />&nbsp;<wbr />&nbsp;<wbr />&nbsp;<wbr />&nbsp;$test_dvd-&gt;changeAllSeriesReleaseDate('2010-04-01');</span></li>
<li><span class="php-code"><wbr />&nbsp;</span></li>
<li><span class="php-code"><wbr />&nbsp;<wbr />&nbsp;<wbr />&nbsp;<wbr />&nbsp;var_dump($test_dvd-&gt;toArray());</span></li>
<li><span class="php-code"><wbr />&nbsp;</span></li>
<li><span class="php-code"><wbr />&nbsp;<wbr />&nbsp;<wbr />&nbsp;<wbr />&nbsp;echo<wbr />&nbsp;&quot;&lt;/pre&gt;&quot;;</span></li>
<li><span class="php-code"><wbr />&nbsp;<wbr />&nbsp;<wbr />&nbsp;<wbr />&nbsp;exit;</span></li>
<li><span class="php-code"><wbr />&nbsp;<wbr />&nbsp;}</span></li>
<li><span class="php-code">}</span></li></ol>上のアクションでは、idが1のdvd_packageデータの発売日(release_date)を１ヶ月遅らせて、<br />
関連するdvd_packageデータの発売日も１ヶ月遅らせようとしています。<br />
結果をみると、、<br />
<a href="/read_file.php?id=1022&mode=1" rel="lightbox" class="link-lightbox"><img src="http://blog.asial.co.jp/read_file.php?id=1022" /></a><br />
<br />
肝心のidが1のdvd_packageデータが2010-03-03のままで、更新できていません。<br />
これは、changeAllSeriesReleaseDateメソッドのforeachの部分が原因です。<br />
$dvdとして自分自身を取得した際に、保存前のrelease_dateが消えてしまったのです。<br />
<br />
保存前、というのが問題なので、<br />
$this->release_date = $date_string;<br />
の後に<br />
$this->save();<br />
を入れれば大丈夫です。<br />
<br />
今まで2回ほどこのようなケースに出会ったことがありましたので、どこかで役立つことがあるかもしれません。 ]]></description>
			<author>牧野克俊</author>
			<category>Tech</category>
			<guid isPermaLink="true">http://blog.asial.co.jp/664</guid>
		</item>
				<item>
			<pubDate>Mon, 15 Feb 2010 12:52:26 +0900</pubDate>
			<title>KeyRemap4MacBookで自分好みにキーをリマッピング</title>
			<link>http://blog.asial.co.jp/663</link>
			<description><![CDATA[ こんにちは、熊谷です。<br />
<br />
Macを使っている上でキーマップをカスタマイズするために欠かせないソフトといえば、<a href="http://pqrs.org/macosx/keyremap4macbook/index.html.ja">KeyRemap4MacBook</a>です。これがないと私はMacを思い通りに使えないと言っても過言ではありません。そんなKeyRemap4MacBook、500種類以上の様々なキーのリマッピングが出来ると言うことで、そのままの状態でもほぼ思い通りにキーをカスタマイズすることが出来ます。<br />
<br />
しかし、こんなに種類があっても個人的にこれがこう出来ると良いのにとちょっとおもったりもします。ということで、カスタマイズです！<br />
<br />
そんなことで、私が行いたいのはYen(\)のリマップです。それだけならこのKeyRemap4MacBookで対応しているんですが、このリマップをX11上では無効にしたいという、「X11上では無効になるYen(\)のリマップ」を追加します。ちなみにMacではYenマークとバックスラッシュは別物になっているので、このリマップがないといろいろ不便です。でも、X11ではXmodmapで<br />
<ol class="boxcode-main no-number"><li>keycode<wbr />&nbsp;101<wbr />&nbsp;=<wbr />&nbsp;backslash<wbr />&nbsp;bar<wbr />&nbsp;yen<wbr />&nbsp;bar</li></ol>としているの、KeyRemap4MacBookのリマップは無効にしたい。ということで先の「X11上では無効になるYen(\)のリマップ」が欲しくなってくると言うことになります。<br />
<br />
で、それを実現するのに必要なものはKeyRemap4MacBookのソースコードとXcodeです。<br />
<br />
<a href='http://pqrs.org/macosx/keyremap4macbook/source.html.ja'>http://pqrs.org/macosx/keyremap4macbook/source.html.ja</a><br />
<br />
KeyRemap4MacBookに自分好みの設定を追加するにはfiles/prefpane/checkbox.xmlに設定を加えコンパイルし直してインストールし直せばOKです。<br />
<br />
<ol class="boxcode-main no-number"><li>&lt;item&gt;</li><li><wbr />&nbsp;&lt;name&gt;Remap<wbr />&nbsp;Yen(\)<wbr />&nbsp;Key<wbr />&nbsp;not<wbr />&nbsp;X11&lt;/name&gt;</li><li><wbr />&nbsp;<wbr />&nbsp;&lt;list&gt;</li><li><wbr />&nbsp;<wbr />&nbsp;<wbr />&nbsp;&lt;item&gt;</li><li><wbr />&nbsp;<wbr />&nbsp;<wbr />&nbsp;<wbr />&nbsp;&lt;name&gt;JIS<wbr />&nbsp;Yen(\)<wbr />&nbsp;to<wbr />&nbsp;Backslash(\)<wbr />&nbsp;not<wbr />&nbsp;X11&lt;/name&gt;</li><li><wbr />&nbsp;<wbr />&nbsp;<wbr />&nbsp;<wbr />&nbsp;&lt;sysctl&gt;remap.jis_yen2backslash_notX11&lt;/sysctl&gt;</li><li><wbr />&nbsp;<wbr />&nbsp;<wbr />&nbsp;<wbr />&nbsp;&lt;not&gt;VIRTUALMACHINE,<wbr />&nbsp;X11&lt;/not&gt;<wbr />&nbsp;<wbr />&nbsp;<wbr />&nbsp;<wbr />&nbsp;<wbr />&nbsp;</li><li><wbr />&nbsp;<wbr />&nbsp;<wbr />&nbsp;<wbr />&nbsp;&lt;autogen&gt;--KeyToKey--<wbr />&nbsp;KeyCode::JIS_YEN,<wbr />&nbsp;KeyCode::VK_JIS_BACKSLASH&lt;/autogen&gt;</li><li><wbr />&nbsp;<wbr />&nbsp;<wbr />&nbsp;&lt;/item&gt;</li><li><wbr />&nbsp;&lt;/list&gt;</li><li>&lt;/item&gt;</li></ol><br />
こんな感じで設定を追加します。&lt;sysctl&gt;にはユニークな名を&lt;not&gt;にはこのリマップを適用しないアプリケーションを記述します（このアプリケーション名については、src/core/bridge/bridge.hppに記述されています。ここに記載されていないものでも、src/core/server/server.cppの該当部分と併せて追記すれば自由に出来るのではないかなぁと）。<br />
<br />
そんなことで、checkbox.xmlに記述したらあとはコンパイル<br />
<ol class="boxcode-main no-number"><li>%<wbr />&nbsp;make<wbr />&nbsp;clean<wbr />&nbsp;all</li></ol>するとパッケージができあがるので、あとは普段通りそのパッケージをインストールすると完了です。<br />
<br />
KeyRemap4MacBookの設定画面に追加した項目が表示されていると思います。<br />
<a href="/read_file.php?id=1021&mode=1" rel="lightbox" class="link-lightbox"><img src="http://blog.asial.co.jp/read_file.php?id=1021" /></a><br />
簡単に自分好みのキーマップを追加できるKeyRemap4MacBook、是非使ってみてはいかがでしょうか。 ]]></description>
			<author>熊谷裕志</author>
			<category>Tech</category>
			<guid isPermaLink="true">http://blog.asial.co.jp/663</guid>
		</item>
				<item>
			<pubDate>Fri, 12 Feb 2010 11:20:57 +0900</pubDate>
			<title>株式会社アシックス社向け、ランナーのためのゲイトアナリシス・ソフトウェアの共同開発　</title>
			<link>http://blog.asial.co.jp/662</link>
			<description><![CDATA[ 最近ランニングがブームを呼んでいますが、私のまわりにも東京マラソンや、サロマ湖 100km ウルトラマラソンに挑戦する方々が、ちらほらいらっしゃいます。<br />
<br />
高校のマラソン大会で5km走ったのが私の最長記録になりますが、フルマラソンでも相当厳しいだろうに、100kmマラソンとは、本当に未知の世界です。話に聞いたところでは、一回の参加で、足の痙攣は当然のごとく、身体のあちこちで異常な症状が起こるとか。。。<br />
<br />
尊敬するとある上場企業の経営者の方が、身体の限界に挑戦し、己と向き合うことで、さらに成長できるとおっしゃっていましたが、なるほどな・・・と思い知らされました。<br />
<br />
<br />
さて、今回は、そんなランナーの皆様にとっての必須アイテム、「ランニングシューズ」を選ぶときに役立つゲイトアナリシス・サービスについてご紹介したいと思います。<br />
<br />
ゲイトアナリシス・サービスとは、ランニング中の様子を後方よりカメラで撮影し、そのフォームをコンピューターで測定、分析することを特徴とします。自分の走り方の癖の発見や、最適なランニング・シューズの選定をすることができます。<br />
<br />
アシアルでは、アシックス・スポーツ工学研究所と共同で、ゲイトアナリシス・ソフトウェア（名称：「ASICS Dynamic FOOT ID」）を開発しました。<br />
<br />
「ASICS Dynamic FOOT ID」では、専用のシューズとハイスピードカメラを用いて、足の動きを測定すると共に、インターネット経由でスポーツ工学研究所に蓄積されたデータをもとにその結果を分析し、精度の高い測定・分析結果をレポートとして提供してくれます。<br />
<br />
<br />
○ [測定画面] トレッドミルでランニング撮影をもとに、プロネーション度合い、ストライド、ピッチを自動計測<br />
<a href="/read_file.php?id=1019&mode=1" rel="lightbox" class="link-lightbox"><img src="http://blog.asial.co.jp/read_file.php?id=1019" /></a><br />
※1 プロネーション：地面の足のねじれの度合いのこと。<br />
※2 ストライド：１歩あたりの歩幅のこと。<br />
※3 ピッチ：１分あたりの歩数のこと。<br />
<br />
○ [レポート例] 解析画像と共に、分析結果をその場でご提供<br />
<a href="/read_file.php?id=1020&mode=1" rel="lightbox" class="link-lightbox"><img src="http://blog.asial.co.jp/read_file.php?id=1020" /></a><br />
<br />
<br />
「ASICS Dynamic FOOT ID」については、現在、ASICS STORE NEW YORK（米ニューヨーク）、ASICS STORE HARAJUKU（原宿）、ASICS STORE LONDON（英ロンドン）、ASICS STORE TAIPEI（台湾、台北）で、利用することができます。<br />
<br />
是非、原宿に向かった際には、ASICS STORE 原宿に立ち寄って、お試しいただけたらと思います！<br />
<br />
<br />
<br />
（参考情報）<br />
○<a href="http://www.asial.co.jp/pressrelease/286" alt="アシアル・プレスリリース">[Asial] プレスリリース：株式会社アシックス向け、ゲイトアナリシス・ソフトウェアを共同開発</a><br />
<br />
○<a href="http://www.asics.co.jp/corp/press/pressdoc/~NT000021DA" alt="アシックス・プレスリリース">[Asics] プレスリリース：ニューヨークにランニング専門の旗艦店「ＡＳＩＣＳ ＳＴＯＲＥ ＮＥＷ ＹＯＲＫ」をオープン</a> ]]></description>
			<author>小林有佳</author>
			<category>日常</category>
			<guid isPermaLink="true">http://blog.asial.co.jp/662</guid>
		</item>
			</channel>
</rss>