読者です 読者をやめる 読者になる 読者になる

Controller, Entityを追加する

Symfony

自分でControllerとEntityを追加するところまでやってみる。

データーベースへの接続を使う

まず下準備としてUserControllerへのroutingを定義する。この程度ならば規約によるroutingとかワイルドカードでの指定とかができそうだが、これは後の調査課題とする。

diff --git a/src/Application/HelloBundle/Resources/config/routing.yml b/src/Application/HelloBundle/Resources/config/routing.yml
index 1520818..d1dd43e 100644
--- a/src/Application/HelloBundle/Resources/config/routing.yml
+++ b/src/Application/HelloBundle/Resources/config/routing.yml
@@ -1,3 +1,7 @@
 hello:
     pattern:  /hello/:name
     defaults: { _controller: HelloBundle:Hello:index }
+
+user:
+    pattern:  /user/:id
+    defaults: { _controller: HelloBundle:User:index }

config.ymlを変更してデーターベースの接続先を設定。

diff --git a/hello/config/config.yml b/hello/config/config.yml
index a4f939c..d273391 100644
--- a/hello/config/config.yml
+++ b/hello/config/config.yml
@@ -15,11 +15,11 @@ web.templating:
 twig.config: ~

 ## Doctrine Configuration
-#doctrine.dbal:
-#    dbname:   xxxxxxxx
-#    user:     xxxxxxxx
-#    password: ~
-#doctrine.orm: ~
+doctrine.dbal:
+    dbname:   sandbox
+    user:     scott
+    password: tiger
+doctrine.orm: ~

 ## Swiftmailer Configuration
 #swift.mailer:

Controllerやテンプレートを置くResource/views以下のディレクトリは、symfony 1.*のproject:moduleコマンドのようなコマンドで作るのではなく、手動でつくるものと推測したので、元のドキュメントにあったのと同じような簡単なControllerを書いた。

DoctrineでSQLを直接発行するやり方は以下のページを参考にした。

<?php

namespace Application\HelloBundle\Controller;

use Symfony\Bundle\FrameworkBundle\Controller\Controller;

class UserController extends Controller
{
  public function indexAction($id)
  {
    $conn = $this['database_connection'];
    $stmt = $conn->executeQuery('SELECT * FROM user WHERE id=?', array($id));
    $user = $stmt->fetch();
    return $this->render('HelloBundle:User:index:twig', array('user' => $user));
  }
}

テンプレートも必要だが、ここでは省略。

ORMを使う

SQLを直接発行するとかないわーということで、以下のページを参考にDoctrineを使う。

Entityの定義はアノテーションで行うことにする。これは良い機能だと思う。

@Entity, @Table, @Columnで対応するテーブルを定義した後、doctrine:generate:entitiesコマンドでgetter/setterを自動生成した。

<?php
// Application/HelloBundle/Entity/User.php
namespace Application\HelloBundle\Entity;

/**
 * @Entity
 * @Table(name="user")
 */
class User
{
    /**
     * @Id
     * @Column(type="integer")
     * @GeneratedValue(strategy="IDENTITY")
     */
    protected $id;

    /**
     * @Column(type="string", length="50")
     */
    protected $name;

    /**
     * Get id
     *
     * @return integer $id
     */
    public function getId()
    {
        return $this->id;
    }

    /**
     * Set name
     *
     * @param string $name
     */
    public function setName($name)
    {
        $this->name = $name;
    }

    /**
     * Get name
     *
     * @return string $name
     */
    public function getName()
    {
        return $this->name;
    }
}

Symfony2.0のドキュメントにはcreateQueryを使ってEntityを作成、変更、削除する方法は書いてあるが、Entityを取得する方法が書いていないのが相当不親切だと思う。ちょっと迷った挙句、Doctrineのドキュメントを参照してようやく分かった。

先ほど書いたControllerのコードをDoctrineを使うように変更。常にnamespaceまで含めてクラス名を書かなくていけないのかはよく分からない。getRepositoryメソッドを使うにしてもやっぱり長いと思う。

<?php

namespace Application\HelloBundle\Controller;

use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Application\HelloBundle\Entity\User;

class UserController extends Controller
{
  public function indexAction($id)
  {
    $em = $this['doctrine.orm.entity_manager'];
    $user = $em->find('Application\HelloBundle\Entity\User', $id);
    return $this->render('HelloBundle:User:index:twig', array('user' => $user));
  }
}

エラー処理を行う

上のUserControllerのコードでは、該当ユーザーが見つからなかった時に何のエラー処理もしていないので、以下のページを参考にしてHTTP 404を返すようにした。

<?php

namespace Application\HelloBundle\Controller;

use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;

use Application\HelloBundle\Entity\User;

class UserController extends Controller
{
  public function indexAction($id)
  {
    $em = $this['doctrine.orm.entity_manager'];
    $user = $em->find('Application\HelloBundle\Entity\User', $id);
    if (is_null($user)) {
      throw new NotFoundHttpException('The uesr does not exist.');
    }
    return $this->render('HelloBundle:User:index:twig', array('user' => $user));
  }
}