Symfony2による実践的アプリケーション開発

 Symfony2による実践的アプリケーション開発

2012年4月7日 関西PHPユーザーズグループ PHP勉強会

Ba8ecb9f1d269e44056ff4e7dca4c5e0?s=128

hidenorigoto

April 07, 2012
Tweet

Transcript

  1. 実 践 編 PHPメンターズ 後藤 秀宣 @hidenorigoto 1

  2. 自己紹介 • 後藤 秀宣(ごとう ひでのり) • @hidenorigoto • インクス株式会社/PHPメンターズ (KnpLabs

    Japanメンバー) • PHPは10年くらい利用 • 日本Symfonyユーザー会 • symfony 1.4の本 2
  3. アジェンダ • 実践編の流れ • 構築するアプリの説明 • Symfony2基礎知識 • 構築 •

    Symfony2インストールと設定の概略、ファイルとディレクトリ、バンドル、ジェネレーター(エン ティティクラスとリポジトリクラス)、エンティティ調整と初期データの投入、ページフローの実 装(ルーティングとコントローラ、テンプレート)、フォームの基本、TwigとSymfonyバインディ ング、フォームとバリデーション、CSRFトークン、フォームの詳細、Doctrine2 ORM基礎、バリ デーション定義、TwitterBootstrapの組み込み、ファンクショナル(受入)テスト、ユニットテス ト 3
  4. 実践編の流れ • 基礎解説 +ライブコーディング +実況解説 • 上記を7イテレーション 質問はイテレーションの区切りor随時 • トイレも随時

    4
  5. 構築するアプリ • アンケート(超簡易版) 5

  6. 要件の整理 • 1回分のアンケート実施のみ • アンケート項目は3タイプ固定 • 選択式1,選択式2、自由記入 • アンケート項目数可変 •

    アンケート設問はDBに入れる • 回答情報もDBに入れる 6
  7. データモデル 7 ઃ ܭ ࡁ 設問項目 回答 回答詳細

  8. データベース 8 mysql> show tables; +-------------------------+ | Tables_in_questionnaire | +-------------------------+

    | answer | | answer_detail | | questionnaire_item | +-------------------------+ 3 rows in set (0.01 sec)
  9. answerテーブル 9 CREATE TABLE `answer` ( `id` int(11) NOT NULL

    AUTO_INCREMENT, `created_at` datetime NOT NULL, `updated_at` datetime NOT NULL, PRIMARY KEY (`id`) ) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8
  10. answer_detailテーブル 10 CREATE TABLE `answer_detail` ( `id` int(11) NOT NULL

    AUTO_INCREMENT, `answer_id` int(11) DEFAULT NULL, `questionnaire_item_id` int(11) DEFAULT NULL, `input` longtext, `created_at` datetime NOT NULL, `updated_at` datetime NOT NULL, PRIMARY KEY (`id`), UNIQUE KEY `questionnaire_item_answer_idx` (`answer_id`,`questionnaire_item_id`), KEY `IDX_DCFF4534AA334807` (`answer_id`), KEY `IDX_DCFF45344DF37C59` (`questionnaire_item_id`), CONSTRAINT `FK_DCFF45344DF37C59` FOREIGN KEY (`questionnaire_item_id`) REFERENCES `questionnaire_item` (`id`), CONSTRAINT `FK_DCFF4534AA334807` FOREIGN KEY (`answer_id`) REFERENCES `answer` (`id`) ) ENGINE=InnoDB AUTO_INCREMENT=11 DEFAULT CHARSET=utf8
  11. questionnaire_itemテーブル 11 CREATE TABLE `questionnaire_item` ( `id` int(11) NOT NULL

    AUTO_INCREMENT, `text` longtext NOT NULL, `answer_type` varchar(255) NOT NULL, `optionality` varchar(255) NOT NULL, `item_number` int(11) NOT NULL, `created_at` datetime NOT NULL, `updated_at` datetime NOT NULL, PRIMARY KEY (`id`), UNIQUE KEY `questionnaireitem_itemnumber_idx` (`item_number`) ) ENGINE=InnoDB AUTO_INCREMENT=11 DEFAULT CHARSET=utf8
  12. 初期データ • 設問項目データが投入されている (questionnaire_item) 12

  13. 回答データ • 回答データが登録されたところ 13

  14. リポジトリ • https://github.com/ phpmentors-jp/kphpug- questionnaire • コミットログとタグで、流れを把握しや すくしてあります。 14

  15. Symfony2の基礎知識 15

  16. アーキテクチャ 16 • サービスコンテナ • Dependency Injectionコンテナ • カーネルとバンドル

  17. サービスコンテナ • オブジェクトの構成に関する知識が集約 された場所 • DependencyInjectionコンポーネントとし て単体で利用可能 • 17

  18. カーネル • アプリケーションの処理を行うための基 本構造 18

  19. カーネル • バンドル機構とWebアプリケーションの基 本処理フローの提供 19

  20. ブログ記事 • PHPメンターズのブログにこのような話を 書いています http://phpmentors.jp/ 20

  21. イテレーション 1 アプリケーションの 枠組みの準備 21 CREATING BUNDLE

  22. Symfony2開発環境準備 • 日本Symfony ユーザー会 「Symfonyの インストールと 設定」 http://docs.symfony.gr.jp/ symfony2/book/ installation.html

    22
  23. $ php app/check.php 動作確認 • コマンドライン • Web http://localhost/ ~hidenorigoto/test/Symfony

    / web/ app_dev.php/ 23 ࠷ॳ͸ඞͣίϚϯυͰ ֬ೝ͢Δ͜ͱ
  24. ファイル構成 24

  25. appディレクトリ配下 25

  26. srcディレクトリ配下 • 実際に自分のソースコードを配置する場 所 • 自分の名前空間 26

  27. バンドルの作成 • コマンドライン 27 $ php app/console generate:bundle ͦ ͷ

    લ ʹ
  28. バンドルの名前、名前空間 • 今から作ろうとしているものは何なのか • 関西PHPユーザーズグループの アンケートアプリケーション • 名前空間:KPHPUG • アプリケーション:Questionnaire

    • バンドル名:QuestionnaireBundle 28
  29. ファイル構成 29

  30. イテレーション 2 ページフローの構築と テンプレートの基礎 30 IMPLEMENTING PAGE FLOW

  31. 実装の流れを俯瞰 31

  32. ページフローに必要なもの • ルーティング/ルート • コントローラから • テンプレートレンダリング • リダイレクト •

    コントローラ、テンプレートでルートに 基づくリンク • CSRFチェック用フォーム 32
  33. 実装するフロー 33 入力画面 確認画面 完了画面

  34. 実装するフロー 34 入力画面 確認画面 完了画面 準備 / GET inputAction /input

    inputPostAction POST confirmationAction confirmationPostAction /confirmation POST GET successAction /success GET ポストバック方式
  35. ルート一覧 35 URL HTTP メソッド コントローラ ルート名 /input GET inputAction

    kphpug_questionnaire_answer_input /input POST inputPostAction kphpug_questionnaire_answer_inputpost /confirmation GET confirmationAction kphpug_questionnaire_answer_confirmation /confirmation POST confirmationPostAction kphpug_questionnaire_answer_confirmationpos t /success GET successAction kphpug_questionnaire_answer_success / GET indexAction kphpug_questionnaire_answer_index php app/console router:debug
  36. Symfonyでのルート定義 • YAMLやXML、PHPファイルでの定義 • 従来のフレームワークに近い • アノテーション(DocBlockコメント)に よる定義 • どれを使っても同等

    • 混在も可能 36 ルーティング http://docs.symfony.gr.jp/ symfony2/book/routing.html
  37. 実際のコード例 37 ルート定義 アノテーション リダイレクト メソッド テンプレート 描画

  38. 実際のコード例 38 ルートからURL生成 (Twig関数) テンプレートの基本(日本Symfonyユーザー会) http://docs.symfony.gr.jp/symfony2/book/ templating.html

  39. 空のフォーム 39 空のフォーム 作成 CSRFだけチェック される

  40. テンプレート(Twig) • テンプレート継承を使ってレイアウト (親)→子のような関係を作れる • PythonのDjango、Jinja2由来の記法 40

  41. 従来のテンプレート 41 コントローラ テンプレート レイアウトテンプレート 埋め込み HTML 親子1階層

  42. Twigテンプレート 42 コントローラ テンプレート 親テンプレート HTML

  43. Twigテンプレート 43 <html> <body> {% block body %} {% endblock

    %} </body> </body> {% extends “layout.html.twig ”%} {% block body %} <h1>見出し</h1> <p>コンテンツです。 </p> {% endblock %} 親 子 子は何階層でも 作れる
  44. テンプレート継承を使う例 44 ああああああああああああ ああああああああああああ ああああああああああああ ああああああああああああ あああ いいいいいいいいいいいい いいいいいいいいいいいい いいいいいいいいいいいい

    いいいいいいいいいいいい いいい うううううううううううう ううう うううううううううううう う ええええええええええ ええええええええええ layout.html.twig single.html.twig 2col.html.twig
  45. イテレーション 3 モデルの準備 45 CREATING ENTITIES

  46. モデルの役割 • 単に永続化(データベースの話)ではない • シンプルなアプリケーションでは、単な るデータ構造のみになるケースが多い • 業務の知識を組み込む場所 • エンティティ、リポジトリ、サービス

    • by DDD(ドメイン駆動設計) 46
  47. Doctrine2 • http://www.doctrine- project.org/ • データマッパー型ORM (Metadata Mapping) • PofEAA

    • Domain Model • Data Mapper • Metadata Mapping • Unit of Work • Repository • マッピング定義はYAML、XML、ア ノテーションどれでも同等 47
  48. Symfony2におけるモデル • フレームワークが直接モデルの機能を提 供しない • DoctrineBridge、DoctrineBundle およびFrameworkBundleによる利用 48

  49. $ php app/console generate:doctrine:entity エンティティクラス作成 • コマンドライン 49

  50. マッピング追加定義 • あくまで「マッピング」であることに注 意 • 「DBスキーマの定義」ではない • マッピングからDBテーブル群を生成す ることも可能 •

    ジェネレータでは指定できないリレー ションの部分を追加する 50
  51. 初期データの投入 • データ投入用コマンドを作る • バンドル配下のCommand ディレクトリに、Symfony \Bundle\FrameworkBundle \Command \ContainerAwareCommandク ラスを継承した

    HogeCommandクラスを作成 51
  52. イテレーション 4 フォームの実装 52 CREATING FORM

  53. Symfonyのフォーム • 送信されたデータの入れ物となるオブ ジェクト(エンティティクラス)と、各 項目の入力用のフィールドのマッピング を行うデータマッパー • FormType • 値の変換(DataTransformer)

    • バリデーション等の呼び出し 53
  54. Formコンポーネント 54 コントローラ (Form)Type AnswerType FormBuilder Form FormView AnswerDetailsType

  55. FormType 55 Person ・name ・address ・bloodType エンティティ フォーム PersonType ・text

    ・text ・choice
  56. FormType 56 Person ・name ・address ・bloodType ・company エンティティ フォーム PersonType

    ・text ・text ・choice ・CompanyType CompanyType ・text ・text ・: Company ・name ・address ・:
  57. 動的にフォーム項目を定義 • 今回のアプリケーションは特殊 • 項目数が可変(実行時に決まる)た め、固定のFormTypeではダメ • FormTypeのbuildメソッド内で、フィー ルドのproperty_pathを調整する(マッ ピング先が決まる)

    57
  58. イテレーション 5 データの永続化 58 STORING DATA

  59. 永続化の基本 • エンティティマネージャオブジェクトを 取得 • エンティティマネージャへ永続化指示 • エンティティマネージャをflush 59 $em

    = $this->get(‘doctrine’)->getEntityManager(); $em->persist($answer); $em->flush();
  60. More DDD Way • エンティティはリポジトリに保存する • リポジトリクラスにaddメソッドを実装 • addメソッド内でpersistするようにす る

    • 保存するオブジェクトの準備やエンティ ティマネージャのflushはサービスに実装 する 60
  61. 実際のコード例 61 リポジトリ

  62. 実際のコード例 62 サービス サービスクラスにユースケースを実装 トランザクション境界にもなる

  63. イテレーション 6 ドメインモデルのテスト 63 TESTING DOMAIN MODELS

  64. 参考資料 • Symfonyドキュメン ト • PHPUnitドキュメン ト 64

  65. ドメイン=自分のもの • 自分で好きなように書く • PHPUnit用のテストケースを書くのみ。 65 サービスクラスのユースケースを中心にテ ストを記述していく

  66. サービスコンテナが必要? • FrameworkBundleのWebTestCaseを継承す る? • いろいろ弊害あり • ComponentFactoryを使う https://github.com/piece/stagehand- componentfactory

    66
  67. イテレーション 7 コントローラのテスト 67 TESTING DOMAIN CONTROLLER

  68. コントローラのテスト • Symfonyドキュメントを参照 • WebTestCase • client、crawler 68

  69. まじめに • コントローラのユニットテスト • ページフローが正しく動作しているか どうかをテスト • DB等にアクセスしない • モックオブジェクトで代用

    69
  70. イテレーション 8 サービス 70

  71. サービス • サービスコンテナへ登録 • オブジェクトの構成に準備が必要な場合 の手間が軽減される(構成の知識を1箇 所に集約できる) • 例:コンストラクタがEntityManagerを 受け取る等

    71 サービスコンテナ http://docs.symfony.gr.jp/symfony2/book/ service_container.html
  72. 参考資料 72

  73. • PofEAA Patterns of Enterprise Application Architecture (Martin Fowler) 73

  74. • DDD (ドメイン駆動設計) Domain Driven Design 74

  75. 75 • 次世代開発基盤技術“Software Factories”詳解 第3回 長期的な要求を定義するフィー チャ・モデル http://www.atmarkit.co.jp/fdotnet/ softfactory/softfactory03/ softfactory03_01.html

  76. 76 ありがとう ございました!