somemo programming etc.

プログラマ、雑記、プログラミング関係はLinkから、数式はこっちでまとめていることが多い

【Symfony2】バンドル作成と、その中身

バンドルというものを作成します。ここまでで、1系と比べるとプロジェクトの作成もせず、appも作成していません。

バンドル

2012/01/29現在、http://symfony.com/doc/current/book/bundles.htmlが404・・・。

プラグインに近く、frontendアプリ、モジュールでもある・・・。いろいろな大きさに設定できるようですね

バンドル作成コマンド

以下のコマンドで作成します。

php app/console generate:bundle --namespace=My/BlogBundle --format=yml

実行後、以下の質問をされます。

Bundle namespace [My/BlogBundle]:
Bundle name [MyBlogBundle]:
Target directory [C:\xampp\htdocs\Symfony/src]:
Configuration format (yml, xml, php, or annotation) [yml]:
Do you want to generate the whole directory structure [no]?
Do you confirm generation [yes]?
Confirm automatic update of your Kernel [yes]?
Confirm automatic update of the Routing [yes]?
  • 名前空間
  • バンドル名
  • コード生成先のディレクトリ
  • 設定ファイルのフォーマット
  • ディレクトリの構造を作るかどうか
  • これまでの構成で生成するかの最終確認
  • カーネルの更新
  • ルーティングの更新

作成されたソース

srcディレクトリにアッパーキャメルで分割したディレクトリが作成されています。その中に各種ファイルがあります。行番号と対応させてみます。

src/My/BlogBundle/Controller/DefaultController.php
                 /DependencyInjection/Configuration.php
                                     /MyBlogExtension.php
                 /Resources/config/routing.yml
                                  /services.yml
                 /views/Default/index.html.twig
                 /Tests/Controller/DefaultControllerTest.php
                 /MyBlogBundle.php
  1. コントローラー:1系のアクションに相当
  2. DI用設定ファイル:よくわからない・・・
  3. DI用拡張ファイル:よくわからない・・・
  4. ルーティング:バンドルごとに存在するっぽい
  5. サービス設定:よくわからない・・・
  6. ビュー:1系のテンプレートに相当
  7. テスト:コントローラー用のテストファイル
  8. バンドルクラス:空っぽ

ルーティング

次のチュートリアルに移る前に動かしてみました。1系と比較して何が変わっているのかを見ながら進めていきます。

まずは、routing.ymlからアクセスURLを特定しました。

MyBlogBundle_homepage:
    pattern:  /hello/{name}
    defaults: { _controller: MyBlogBundle:Default:index }

1系と同様に/hello/123と適当にアクセスするようにします。nameの部分が:nameではなく、{}にするようになっています。

次に、MyBlogBundleのDefaultControllerのindexアクション(1系と同じだそうです)を探しました。バンドル:コントローラ:アクションの並びになっています。

コントローラ

<?php

namespace My\BlogBundle\Controller;

use Symfony\Bundle\FrameworkBundle\Controller\Controller;


class DefaultController extends Controller
{
    
    public function indexAction($name)
    {
        return $this->render('MyBlogBundle:Default:index.html.twig', array('name' => $name));
    }
}

次に、MyBlogBundleのDefaultControllerにindexアクションが存在していました。

アクションの引数に、$nameがあります。1系では、どうなっていたか忘れたのであとでメモ・・・。

アクションの処理は、MyBlogBundleのVIEWディレクトリのDefaultディレクトリに存在するindex.html.twigを指定し、変数を連想配列に格納しています。そのままrenderメソッドを実行しているので、テンプレートを表示しているようです。

1系では、マジックメソッド__setと__getを利用してメンバ変数として格納し、最終的には連想配列にしてテンプレートで使用していました。

また、テンプレートの接尾辞であったSuccessがなくなっています。エラー時に切り替わるのが面倒だったのでうれしい変更です。それでは、Symfony2から採用されているtwigを見てみます。

twig

Hello {{ name }}!

これだけです。twigについては、また後でメモすると思います。{}2つに囲まれたnameはコントローラで連想配列に格納したname変数として展開されます。つまり、今回のアクセスに対するレスポンスは「Hello 123!」となります。ちなみに、htmlソースを表示しても、「」内と同じ内容でした。

テスト

以下、コントローラのテストファイルです。

<?php

namespace My\BlogBundle\Tests\Controller;

use Symfony\Bundle\FrameworkBundle\Test\WebTestCase;

class DefaultControllerTest extends WebTestCase
{
    public function testIndex()
    {
        $client = static::createClient();

        $crawler = $client->request('GET', '/hello/Fabien');

        $this->assertTrue($crawler->filter('html:contains("Hello Fabien")')->count() > 0);
    }
}

テストも軽くやりたかったのですが、app/cosoleを実行してtestで検索しても何もなかったのであきらめました。ファイルの中身は、1系のlimeにあったsfBrowserと似たものを使用し、リクエストを発行してレスポンスを確かめられそうな感じです。

また、WebTestCaseはPHPUnit_Framework_TestCaseを継承したSymfony2のテストケースクラスです。$this->assertTrueもTDDを学んだ時に使用しているので、とても身近に感じます。他にも機能テスト用のテストケースクラスや、セキュリティ特価のテストケースクラスもありました。

その他

1系を触っていたおかげで、バンドル作成の段階で得るものが多かったです。5.3系の特徴である名前空間や静的遅延束縛なども見慣れてきました。Symfony2なら5.4のTraitも導入すると思うので、早くSymfony2に慣れて、設計思想を理解できるようになっていきたいです。