アシアルブログ

アシアルの中の人が技術と想いのたけをつづるブログです

Symfony 2のアプリケーション構成を読む

こんにちは。小川です。
今週からアシアルのオフィスの一部でフリーアドレス制度が導入されました。
もしフリーアドレスを実施している会社にお勤めの方がいましたら、導入のアドバイスとか、おすすめのグッズなどがあれば教えてください!
(今までは机の上にぬいぐるみなどを置いていたりしたのですが、移動が面倒になった分遊び心がもてなくなってしまい面白くないので、そのあたり工夫されていることがあればぜひ!)

さて、今回のテーマはSymfony 2です。先月なかごろにプレビュー版がリリースされました。ご存じの方もいらっしゃると思います。

今回はSymfony 2の特徴に加え、実際にSymfony 2で作るアプリケーションの構成はどのようになるか、ということをお話ししたいと思います。

------------------------------------------
追記
Symfony Componentsシリーズ始めました!
<Symfony Componentsシリーズ(1)> オブジェクトをつなぐEvent Dispatcher
<Symfony Componentsシリーズ(2)> Symfony 2の秘密兵器: Request Handler
------------------------------------------


まずはSymfony 2の特徴をざっくり書いてみたいと思います。

PHP 5.3以降に対応
PHP 5.3といえば名前空間です。Symfony 2.0は名前空間を利用しています。これによりコードがシンプルになります。またクラス名や関数名の衝突を気にする必要がなくなります。

◆シンプル・高速
symfony 1系はよく重いといわれます。この点が大幅に改善されたようです。
とりわけ変わっているのがアクションにたどり着くまでのプロセスです。アプリケーションの中核となるクラスがSymfony\Foundation\Kernelです。このクラス自身はとてもシンプルに作られています。
また、Requestを受けてResponseの作成までの一連の処理を担うSymfony\Components\RequestHandler\RequestHandlerクラスもとてもシンプルに作られています。
この2つのクラスがアプリケーション全体の流れを構成します。シンプルな流れの中に必要に応じて処理を組み込んでいく、というのがSymfony 2のスタンスとなります。

◆DIコンテナ
Symfony 2にはオブジェクトの依存性をなくすためのコンポーネントが2つあります。1つは以前から実装されていたEventDispatcherです。そして新たに実装されたのがDependencyInjectionというコンポーネントです。
Dependency Injectionについては、Fabien氏のブログを読むと分かりやすいと思います。(What is Dependency Injection?)
これによりフレームワークの拡張がより簡単になります。DIがよくわからない人も、多分使うようになるとわかるかなと思いますので、あまり心配しなくてもよいでしょう。

◆Doctrine 2
ORMであるDoctrineも新しいものになります。これも以前のDoctrineに比べてとても高速で軽量になります。Symfony自体の軽量化と合わせて、大きなパフォーマンスの改善が見込めそうです。

Zend Framework
Symfony 2から、ログとキャッシュにZend Frameworkを利用するようになります。SwiftMailerやDoctrineもそうですが、他のフレームワークとの連携を行うことでより品質の高いものができると思いますのでいいことかなと思います。


さて、変更点をいくつかあげてみましたが、実際にSymfonyで作るアプリケーションがどのようになるのかはわからないかと思います。
現在GitHub上にsandboxが上がっていますので、それを見てみるのが手っ取り早いと思います。

sandboxにはHello Worldに毛が生えた程度のアプリケーションが最初から含まれています。
では実際にディレクトリ構成やクラスの内部など、簡単に説明していきます。


まずはsandboxのディレクトリ直下です。hello, src, webという3つのディレクトリがあると思います。ファイルはどうでもいいので無視です。


### webディレクト

一番とっつきやすいのはwebでしょう。従来のwebと同じように、ドキュメントルートとなるディレクトリです。
中には見慣れたファイルがあると思います。index.phpとindex_dev.phpは依然と同じくフロントコントローラで、index_dev.phpは開発環境用のフロントコントローラにあたります。

次にhelloとsrcです。どちらも今までのディレクトリ構成にはなかったものです。
中身がシンプルなのはhelloディレクトリのほうなので、そちらから先にみていきます。


### helloディレクト

helloディレクトリの中身は次のようになっています。



HelloKernel.php  cache/  config/  console  logs/


先ほど説明をしたKernelというものが出てきます。Kernelの中にはいくつかのメソッドが実装されています。簡単に説明します。

◆registerRootDir()
Kernelのルートとなるディレクトリです。またカーネルを配置してあるディレクトリ、ここではhelloがカーネルの名称、つまりアプリケーションの名称となります。

◆registerBundles()
Bundleとは日本語にすると束とか1つにまとめたものという意味です。このBundleはSymfony 2では非常に重要な役割を持ちます。
このメソッドの中でZendBundleやDoctrineBundleを返しているのをみると、Bundleは従来のPluginのように思われるかもしれませんが、あながち間違いではないでしょう。
このメソッドはアプリケーション = Kernelで必要となるBundleをKernel自身に登録するメソッドです。

このメソッドの中で返している配列の最後に、Application\HelloBundle\Bundleというクラスを渡しています。
Application\HelloBundleという名前空間から想像がつくかもしれませんが、これはアプリケーションの実態です。
実際にBundleにどういったものが含まれるのかは後ほど説明します。

◆registerBundleDirs()
Bundleが配置してあるディレクトリを登録します。名前空間を修飾したクラス名のプレフィックスに応じて設定します。

◆registerContainerConfiguration()
DIコンテナのKernelごとの設定の読み込みを行います。基本的にはBundle単位で設定されていますが、必要に応じて追加・修正などを行うものと思われます。

◆registerRoutes()
ルーティングの設定の読み込みを行います。従来はアプリケーションごとにrouting.ymlがあり、もしプラグインでモジュールが提供されていればそれに対するルーティングを1つずつ定義するようになっていました。
今回はBundle単位でrouting.ymlの定義が可能になっています。その設定を別のrouting.ymlからまとめて読み込む、ということが可能になりました。
ルーティングの仕組み自体は基本的には従来と同じような感覚で使えるのかなと思っています。


Kernelクラスをざっと説明しましたが、基本的にはこれらの内容が記述された状態で自動生成することになるのかなと思います。
内部が柔軟な仕組みなので、こうしてある程度定義されているほうが修正がしやすいと思います。

さて、Kernelクラスの説明が終わったら、あとは大したことありません。
logsとcacheは名前の通りログとキャッシュが保存されます。キャッシュにはDIコンテナの情報やルーティング関連などが出力されるようです。
前回同様にこのディレクトリにはWebサーバからの書き込みを許可するようにパーミッションの設定が必要になります。

consoleというファイルはコマンドです。従来のsymfonyコマンドのように、このコマンド経由でスケルトンの生成などを行うことになると思います。
また--shellオプションを付けると対話式のシェルとして実行可能なので、コマンドを連続して実行するときには便利かと思います。
現在そこまでコマンドは多くないので、実装が固まってきたらより突っ込んでみていきたいと思います。

helloディレクトリの中でほかに説明していないのは残すところconfigディレクトリだけになりましたが、すでに中に入っているファイルに関して触れてしまっていますね。
Symfony 2にはDIコンテナがありますので、基本的にはDIコンテナに必要な修正をYAMLに書き足していくようになるのでしょうか。
DIコンテナの設定をするためのファイルは1つでなくてもいいようなので、役割に応じてYAMLファイルを追加するようになるのかと思います。
現状は必要最低限の設定ファイルだけを配置している可能性もありますし、このあたりの設定に関してはなんとも言えないところです。


さて、helloディレクトリの中をざっくり説明しました。
要するに、アプリケーションとしての設定関連をまとめたディレクトリでしょうか。
Kernel次第でアプリケーションの内容をごっそり切りかえることも可能になります。
読み込むBundle次第で、複雑なアプリケーションにもなりますし、簡潔なアプリケーションにもなるでしょう。
従来のsymfonyでは小さなアプリケーションでも様々な処理を必要としていましたので、いくらでも簡潔に作れるというのは大きな魅力だと思います。


### srcディレクト

さて、残っているのはsrcディレクトリです。まずはディレクトリ構成を見てみます。



Application/  Bundle/  autoload.php  vendor/


実際のロジックが詰まったBundleがこのsrcディレクトリに入るようになります。

ApplicationにはApplicationとして動作させるためのBundleが入ります。中にはHelloBundleというBundleがありますのでわかりやすいですね。

Bundleディレクトリは空っぽです。このディレクトリは従来ののプラグインのような形で、様々なBundleを入れていくのかなと思います。

autoload.phpはオートロードに関するファイルですので特に気にしないでいいでしょう。

そしてvendorです。sandboxではsymfonyやDoctrineなどのコードが含まれています。Bundleではなく外部ライブラリを使いたい場合は、このディレクトリに配置します。

今回だけでは説明しきれないので、helloアプリケーションのロジックが詰まっているHelloBundleだけ説明します。
Applicationディレクトリの中にHelloBundleというディレクトリがありますが、これがHelloBundleです。
中身は以下のようになっています。



Bundle.php  Controller/  Resources/


全てのBundleに共通しているのは、BundleのディレクトリにはBundle.phpというクラスファイルが存在しています。
デフォルトでは空のクラスになっていると思いますが、BundleごとのDIコンテナの設定などが必要な場合はここに処理を追加していきます。

次にControllerディレクトリです。名前からも想像がつくと思いますがControllerクラスを配置します。
ControllerディレクトリにはHelloController.phpがありますのでみてみます。



<?php

namespace Application\HelloBundle\Controller;

use Symfony\Framework\WebBundle\Controller;

class HelloController extends Controller
{
  public function indexAction($name)
  {
    return $this->render('HelloBundle:Hello:index', array('name' => $name));
  }
}


indexAction()メソッドがアクションになります。引数で$nameを受け取っていますが、Symfony 2ではルーティングと連動して引数を受け取るようになります。

Controllerはこの程度にしておいて、Resourcesを見てみましょう。configとviewディレクトリがあると思います。
configにはrouting.ymlがありますので見てみましょう。



hello:
  pattern:  /hello/:name
  defaults: { _bundle: HelloBundle, _controller: Hello, _action: index }


今までのものとなんとなく似ていますね。pattern属性に:nameという部分がありますが、この部分がHelloControllerのindexActionへ引数として渡されます。
それ以外のものはアクションの中で $this->getRequest()->getParameter($key) としてやれば取得可能なようです。

そして最後にviewです。テンプレートですね。従来のsymfonyはテンプレートが各モジュールのディレクトリに分散していました。
複数のテンプレートを修正したい場合にとてもめんどうくさかったりしましたし、デザイナーさんにとってもあまりうれしくないことでした。
Symfony 2からはviewディレクトリ内に全てのテンプレートファイルが入るようになります。もちろんTemplatingコンポーネントのおかげで、Twigなどのテンプレートエンジンも利用しやすくなっていますし、全体に比べると地味な変更かもしれませんが、わりとうれしい変更です。


さて、結局色々話してしまいましたが、Symfony 2.0のアプリケーションのイメージは少し湧きましたか?
実際にはここにDoctrineが入ってきたり、様々なBundleを実際にくみわせたりして開発することになると思います。

まだまだプレビューリリース版ですから、これから様々な機能が追加されてより洗練されていくことでしょう。
現状ではとても実戦投入はできそうにないですが、なんとなくSymfony 2がどのようになるかわかっていただければいいかなと思います。

今後もSymfony 2の情報を追い続けようと思いますので、コマンドなどが充実してきたら実際にアプリケーションの作り方などをご紹介できればと思っています。
とはいえ現状全然内部を追えていないので、まずはじっくりと調べていこうと思います。