前回 Post
エンティティと Comment
エンティティの関連付けを行いました。
ですので、今回は Post
の表示画面に Comment
の入力フォームを作ってみましょう。
テンプレートエンジンは Twig
機能的にはSmarty3に似ています。 Twigの開発元はSymfony2と同じSensioLabです。 テンプレートがコンパイルされて、ネイティブなPHPクラスに変換される部分が大きな特徴です。
タイプ量はかなり削減できます。
{# コメント #}
{# 出力: <?php echo $var?> と同じ #}
{{ var }}
{# フィルタ(変換)<?php echo htmlspecialchars($var, ENT_QUOTES, 'utf-8') ?> と同じ #}
{{ var|escape }}
CommentController を console から生成
$ php app/console generate:controller
------------------------------------------------
Welcome to the Symfony2 controller generator
------------------------------------------------
Every page, and even sections of a page, are rendered by a controller.
This command helps you generate them easily.
First, you need to give the controller name you want to generate.
You must use the shortcut notation like AcmeBlogBundle:Post
Controller name: QuartetBlogBundle:Comment
Determine the format to use for the routing.
Routing format (php, xml, yml, annotation) [annotation]:
Determine the format to use for templating.
Template format (twig, php) [twig]:
Instead of starting with a blank controller, you can add some actions now. An action
is a PHP function or method that executes, for example, when a given route is matched.
Actions should be suffixed by Action.
New action name (press <return> to stop adding actions): createAction
Action route [/create]:
Templatename (optional) [QuartetBlogBundle:Comment:create.html.twig]:
New action name (press <return> to stop adding actions):
-----------------------------
Summary before generation
-----------------------------
You are going to generate a "QuartetBlogBundle:Comment" controller
using the "annotation" format for the routing and the "twig" format
for templating
Do you confirm generation [yes]?
-------------------------
Controller generation
-------------------------
Generating the bundle code: OK
-----------------------------------------------
You can now start using the generated code!
-----------------------------------------------
$
これで CommentController.php
と createAction
が生成されます。
Comment フォームを consoleから生成
$ php app/console doctrine:generate:form QuartetBlogBundle:Comment
The new CommentType.php class file has been created under /usr/local/var/www/symfony-blog-tuts/src/Quartet/Bundle/BlogBundle/Form/CommentType.php.
$
これで CommentType.php
が生成されます。
PostController::showActionにCommentTypeを表示するようにします。
記事表示画面の下にコメント欄がある典型的な感じです。
CommentType
からフォームのViewを作ります。
下記の処理を追加します。
- Formオブジェクトを作成
- FormViewオブジェクトに変換
- レスポンスに追加する
<?php
//PostController
// ↓2行追記
use Quartet\Bundle\BlogBundle\Entity\Comment;
use Quartet\Bundle\BlogBundle\Form\CommentType;
/**
* Finds and displays a Post entity.
*
* @Route("/{id}", name="post_show")
* @Method("GET")
* @Template()
*/
public function showAction($id)
{
$em = $this->getDoctrine()->getManager();
$entity = $em->getRepository('QuartetBlogBundle:Post')->find($id);
if (!$entity) {
throw $this->createNotFoundException('Unable to find Post entity.');
}
$deleteForm = $this->createDeleteForm($id);
// ↓追記
$commentForm = $this->createForm(new CommentType(), new Comment());
return array(
'entity' => $entity,
'delete_form' => $deleteForm->createView(),
// ↓追記
'comment_form' => $commentForm->createView(),
);
}
追加するとこんな感じになると思います。
FormをViewにレンダリング
CommentType
を修正
<?php
// CommentType
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
//->add('post') コメントする際に投稿を選ぶ事はないので削除
->add('content')
;
}
次に BlogBundle/Resources/views/Post/show.html.twig
を開いてViewを編集します。
form_widget()
に PostController
から渡した FormView
オブジェクトを渡すといい感じにフォームを表示してくれます。
// BlogBundle/Resources/views/Post/show.html.twig
<form action="" method="post">
{{ form_widget(comment_form) }}
<input type="submit" value="送信" />
</form>
他にも方法は色々あります。
{# formタグを関数で記述する方法 #}
{{ form_start(comment_form, {'action': path('$routingName'), method: 'POST'}) }}
{{ form_widget(comment_form) }}
<input type="submit" value="送信" />
{{ form_end(comment_form) }}
{# 全てを1つの関数で記述する方法 #}
{{ form(comment_form }}
フォームのレンダリングに関しては[Rendering a Form in a Template | Forms (current) - Symfony](http://symfony.com/doc/current/book/#rendering-a-form-in-a-template)に詳しいドキュメントがあります。 |
URLを<form>に設定
Symfony2はリバースルーティングする際に ルーティングの名前 を利用します。
補足: ルーティング ブラウザがリクエストしたURLに対して、どのアクションを実行するか?という設定の事。
補足2: リバースルーティング ルーティングの逆の事(アクションを指定してURLに変換する。) ユーザーにURLを提供する為に、プログラム上にURLを書くのはナンセンスです。 ([URL → アクション]の定義をルーティングで定義しているから、アクションを指定すればURLぐらい作れるだろう。というお話。)
今回はルーティングの設定をAnnotationで行っているのでルーティングの設定は、 各コントローラーのメソッド に書いてあります。
<?php
// CommentController.php
class CommentController extends Controller
{
/**
* @Route("/create") <- これ
* @Template()
*/
public function createAction()
{
}
}
デフォルトのままだとルーティング名がないので設定します。 ついでに色々ないので設定します。
- どの
Post
のコメントなのか分からないので、post_id
パラメーター - コントローラーに プレフィックスルーティング
<?php
// CommentController.php
use Symfony\Component\HttpFoundation\Response;
class CommentController extends Controller
{
/**
* @Route("/create/{post_id}", name="comment_create")
* @Template()
*/
public function createAction($post_id)
{
return new Response("PostId:{$post_id}");
}
}
ルーティング名を設定したのでフォームに記入
// Post/show.html.twig
{# path(~) の部分です。パラメーターを忘れた時は例外が出るのでミスはすぐに分かります。 #}
{{ form_start(comment_form, {'action': path('comment_create', { post_id: entity.id }), method: 'POST'}) }}
{{ form_widget(comment_form) }}
<input type="submit" value="送信" />
{{ form_end(comment_form) }}
これで、記事ページにコメント欄が表示されるようになります。
補足: コンソール php app/console debug:router で全てのルーティングを確認できます。
表示してみましょう
http://localhost/sf-blog-tuts/web/app_dev.php/post/1
コメント欄が表示されました!
コメントを入力して送信してみると、Post.id
が渡せている事が分かります。