エンジニアの僕が技術関連のメモ等をつらつらと。この広告は、90日以上更新していないブログに表示しています。15日目の記事です(当日0時過ぎに枠が空いてる事に気づいて急遽書きました。documentationから抜粋翻訳)でした。3.0になって少し変わりました。変更点をまとめるとこんな感じです。2系でも実現可能です。post-install-cmd実際にGitHubに公開してみたので気になる方は要チェック!(2系と3系の差分はこちら)appディレクトリがすっきりするので、個人的にvarディレクトリのアイディアが気に入ってます。WiringとPHP-DIです。前回は@77webさんのSymfonyのFormをテストするとき、どんなテストクラスを書くべきか?でした。お話とSymfonyでの導入例を紹介したいと思います。PlayComposerの登場により、昨今のPHPの開発現場でサードパーティ製のパッケージを使う事は当たり前となりました。PSRの発足とComposerのオートローダーの機構により、利用者は労する事なくパッケージクラスの利用に集中できるようになったのです。PHPクラスの他に、Twigテンプレートや言語カタログ、WebアセットなどのリソースはComposerの恩恵を受ける事ができず、これらを含むパッケージを利用する場合は手動でプロジェクトへの統合(通常、ロケータへパスを通す作業)が必要です。非常に大きなパッケージではクラスが抽象化されており、実際に利用する前に多数の設定を書く必要があります。この問題は通常、大手のフレームワークに大抵備わっているモジュールシステム(Symfonyで言うとBundle)の上で配布する事で解決します。TwigやDoctrineと言った主要なパッケージは各フレームワーク用に統合するためのモジュールが作られています:しかし、当然ながらこれらのモジュールはそのフレームワーク用に特化しており、それぞれ一定の規約がある為、別のフレームワークを使用したプロジェクトに導入するのは困難です。これを解決する為に考えられたのがPuliです。カタカナにするとプーリーでしょうか。語源は犬のPuli)から来ているらしいです。Playを実現しようとしているか、またプロジェクトでどのように活用していくかをSymfonyを使ってその一部分をご紹介します。startedInstallation※Puliは現在BETAバージョンとして公開されています。実際の製品で使う場合は注意して下さい。今回使用したPuliのバージョンは1.0.0-beta9でした。本当は3でやりたかったのですが、Puliの対応が不十分な為やむなく2系を使う事にしました。2.8幸いPuliはSymfonyのBundleを提供している為、導入は簡単です。以下の3つパッケージを定義し、インストールします。Pluginによる物で、後述するパスマッピングのログです。これがパッケージ設定ファイルとなる訳です。インストールしたパッケージの全ての設定と共にマージされ、ビルドされます。ディレクトリ内に生成されます。追加した方が良いでしょう。ResourcesビルドされたPuliパッケージのリソースは全てResourceRepositoryに集約されます。Bundleのリソースへのマッピングが定義されている為、すぐに試す事ができます。/_wdt画面をリロードしても問題なくプロファイラーが表示されると思います。次に、プロジェクトのリソースへのマッピングを定義してみましょう。"app/config"}※キー名はパッケージ毎にユニークになるような名前を付ける必要があります。基本的にはPSR−0の名前空間に準拠した命名規則に従えば問題無さそうです。build音沙汰、無し!wですがきちんとビルドされてます。routing部分を次のように置き換えます。...画面をリロードしてもエラーなく画面が表示されるはずです。ような定義をPuliを使う事で正規化する事が可能となります。Package最後にパッケージの配布方法を紹介します。puli.jsonこの構成に則ってテストパッケージを作成しました。World!と表示するTwigを1つ作成し、リソースのマッピングを定義しているだけとなります。このパッケージを試しにインストールしてみます。}]※Packagistに登録していないのでリポジトリを直接指定しています。World!と表示されれば成功です。DiscoveryPuliには、Discoveryと言う概念が存在します。PuliパッケージのリソースがRepositoryに集約されると言う話は前章でしました。Discoveryは、集約したリソースの集合をグルーピングします。これにより、そのリソースが特定のライブラリの為に存在すると言う意味付けをする事ができます。最終的に一つのグループがデファクトスタンダード化すれば、各パッケージはそのグループに所属するようリソースを定義づける事で、いかなるフレームワーク上でも特定のライブラリのリソースを最小限のコード量で集約する事が可能となります。実装例については、Symfonyの話から大きく逸脱してしまう為、詳しくはドキュメントをご覧ください。Calendarなので多くは語りません。Puliについては僕自身も最近注目した物で、解釈を誤っている可能性が大いにあります。Puli自身、開発途上なので皆さんどんどんお試し頂いて、その発展に貢献しましょう!パッケージマネージャは広く普及してその真価を発揮すると思いますので。今ならPRを送ればすぐマージされるかもしれませんよ(笑)なお、今回作業したプロジェクトはGitHubに公開してあります。Calendarも最終週、残す所あと5日となりましたね。LiipFunctionalTestBundleは、以前日本Symfonyユーザ会でも紹介されていたSymfonyアプリケーションのファンクショナルテストの作成を補助するバンドルで、これを使うとファンクショナルテストを少し楽に書く事ができます。今回はこのバンドルを使ったファンクショナルテストの書き方の例を紹介します。インストールComposerでインストールします。liip/functional-test-bundleKernelにバンドルを追加します。trueこうする事でテスト用のDBエンジンにSQLiteが使用され、テストで使用するフィクスチャを初期化するのが非常に楽になります。実際に使用するDBエンジンと互換性があれば、この設定は非常に便利です。これで準備はOKです。通常、Symfonyのファンクショナルテストを書く時はFrameworkBundleのWebTestCaseを継承しますが、今回はLiipFunctionalTestBundleのWebTestCaseを継承します。WebTestCase{}実際はこのWebTestCaseは、FrameworkBundleのWebTestCaseを継承しているので使い勝手はさほど変わりません。代わりにいくつかのショートカット機能を備えています。フィクスチャの読み込み多くのファンクショナルテストがテスト用のフィクスチャを読み込む必要がありますが、LiipFuncionalTestBundleではそれが非常に簡単に行えます。※予めプロジェクトにDoctrineFixturesBundleをインストールしておく必要があります。]);}引数には、配列で読み込みたいフィクスチャのクラスをFQCNで定義します。この時、先ほど設定でDBエンジンをSQLiteにしていれば、自動的にスキーマを初期化した上で読み込んでくれます。'AppBundle\DataFixtures\ORM\LoadUserData',]);何気に面倒ですが、スーパークラスやトレイトに定義しておけば問題ないと思います。仮想クライアントを作成してリクエストを送信しますが、ページがユーザの認証を必要としている場合、少々面倒ですよね。この為、LiipFunctionalTestBundleでは予めユーザを認証させた状態のクライアントを作成することができます。使用する必要がある点だけ注意して下さい。$this->makeClient();コンソールコマンドの実行コンソールコマンドの実行も非常に簡単です。]);}第1引数にコマンド名、第2引数にパラメータを指定します。返り値には標準出力に表示される結果がそのまま文字列で返されます。その他にHTML5のバリデーションや、DIコンテナのサービスIDから該当クラスのモックを作ったり、色々便利な機能が満載です。これから、Symfonyでファンクショナルテストを作る方は是非試してみて下さい。当初はFormについて何か書く予定でしたが、どうしても長くなってしまうのでRoutingについて書こうと思います。Annotationなど様々な形式でルートを設定する事ができますが、皆さんは何で設定していますか?僕はYAMLとAnnotationの両方をよく使います。Webアプリケーションでは、エンドユーザ向けやシステム管理者向けと言った、複数のサイト構成を取る事が多いと思います。その場合、サイト毎の共通設定をYAML、ページ毎の設定をAnnotationで設定します。ディレクティブを設定していますか?勿論、サイト毎に異なるドメインを使う場合はしていると思いますが、上記のように同じドメインを使う場合はしていない方もいると思います。そもそもホストルーティングはHTTPサーバがやってくれるので、URLマッチングでは必要ありません。これらの設定はURL生成でも使われる為、きちんと設定していないと問題が起きる事があります。コメントアウトして試してみましょう。}}上記3パターン、いずれも結果はこうなります:http://app.com/administration/dashboardURLは正しく生成されました。エンドユーザ向けに配信されるメールに使われるURLがこうなってしまったら大変ですね。コンソールだと正しいURLが作られないのでしょうか?答えはドキュメントに書いてあります。オブジェクトのホストが使用されます。オブジェクトで明示的にホストを指定してください。Symfony2日本語ドキュメント具体的には、HttpKernelのonKernelRequestイベントでRequestContextにサーバ情報が渡されます。なってしまった訳です。ドキュメントに沿って、URL生成前にRequestContextにホストを指定してやれば正しく動作するのですが、実はRouterは対象のルートにホストが設定されている場合はそちらの値を使用します。ディレクティブの設定をした方が簡単かつ安全です。使ってテスト環境だけSQLiteで動作するようにしているのですが、ある時から途中でDBがロックしてしまい、テストスイートがパスしなくなってしまいました。locked原因を探っていくうちに、以下のテストケースに問題がある事が分かりました。$iterator->current()[0]);実際にアプリケーションでも大量の結果セットを返す可能性のある::createHogeQuery()はiterate()して使っていたのでテストも同様にしたのですが、横着したのがいけなかったようです。言う事かと言うと、iterate()を使う場合は最後の行までフェッチしないと、内部のPDOStatementがcloseCursor()されないようで、その結果次回以降のテストに影響が出ていたと言うわけです。テストに以下を追加する事でとりあえず解決しました。cleanupあるいは、テストデータの量はたかがしてれているのでそもそもテストではiterate()を使わなければ良いのかもしれません。ところでこれ、普通にforeachしたとしてもbreakされたら同様の事が起きそうですよね。誰か試してみて下さい。ブログを報告するスターをつけました引用をストックしましたストック一覧を見る閉じる引用するにはまずログインしてくださいログイン閉じる引用をストックできませんでした。再度お試しください閉じる限定公開記事のため引用できません。