Symfonyではデータベース(以下、DB)とデータをやり取りするのに、DoctrineというORMを使います。ORMとはDBのデータとPHPのクラスをマッピングして変換する技法のことです。
ここでは、おみくじの運勢をDBに格納し、Doctrineを使って操作するようにアプリケーションを変更します。
まずは、DBの設定を行います。ここでは、簡単に利用できるSQLiteを使用します。下記のように設定ファイルを修正します。
... # Doctrine Configuration doctrine: dbal: # pdo_sqliteに変更します driver: pdo_sqlite # 追加します path: "%database_path%" ...
parameters: ... # You should uncomment this if you want use pdo_sqlite # コメントアウトしてパスを変更します database_path: "%kernel.root_dir%/../var/data.db3" ...
parameters: # 追加します database_path: "%kernel.root_dir%/../var/data.db3" ....
SQLiteのDBファイルを作成します。
$ touch var/data.db3
DoctrineではPHPのクラスを作成してから、それを基にしてDBのテーブルを作成します。DBのテーブルにマッピングするクラスをEntityと言います。
consoleコマンドを使って、Unseiエンティティを生成します。
$ php bin/console doctrine:generate:entity The Entity shortcut name: AppBundle:Unsei [Enter] Configuration format (yml, xml, php, or annotation) [annotation]: [Enter] New field name (press <return> to stop adding fields): [Enter] > Generating entity class src/AppBundle/Entity/Unsei.php: OK! > Generating repository class src/AppBundle/Repository/UnseiRepository.php: OK!
Unsei.phpと一緒にUnseiRepository.phpも作成されました。後者のクラスをリポジトリと言います。リポジトリとは一般的に何かを保管している所という意味です。DBで例えると、リポジトリがDBテーブルで、エンティティがDBテーブルの行(row)にあたります。Unseiエンティティを取得するときには、UnseiRepositoryに問い合わせてUnseiエンティティを取得することになります。
EntityとRepositoryはMVCパターンに当てはめるとModelの位置付けになります。
Unsei.phpの中身を見てみましょう。
<?php namespace AppBundle\Entity; use Doctrine\ORM\Mapping as ORM; // (a) /** * Unsei * * // ① * @ORM\Table(name="unsei") * // ② * @ORM\Entity(repositoryClass="AppBundle\Repository\UnseiRepository") */ class Unsei { /** * @var int * * // ③ * @ORM\Column(name="id", type="integer") * @ORM\Id * @ORM\GeneratedValue(strategy="AUTO") */ private $id; // ④ /** * Get id * * @return int */ public function getId() // ⑤ { return $this->id; } }
① アノテーションを使って、UnseiクラスをDBのunseiテーブルにマッピングしています。(a)でDoctrine\ORM\Mapping
クラスをインポートしてORM
という別名を付けています。Doctrine関連のアノテーションは全て@ORM\XXXX
となります。
② Unseiエンティティに対するRepositoryを定義しています。先ほど一緒に作成されたUnseiRepository
が定義されています。
③ idプロパティとDBテーブルのカラムをマッピングしています。マッピング先がinteger型のidカラムであり、ID(プライマリーキー)であること、自動で値を割り当てることが定義されています。
④ idプロパティが生成されています。Entityはオブジェクトを一意に識別する為にidプロパティを持ちます。
⑤ idのGetterも生成されています。
@ORMアノテーションを使って、EntityとDBのテーブルクラスをマッピングする。 Entityはオブジェクトを一意に識別する為のidを持つ。
Unseiクラスにnameプロパティを追加します。
... class Unsei { ... private $id; /** * @ORM\Column(name="name", type="string") // ① */ private $name; ... }
① nameプロパティを追加し、DBテーブルのstring型のnameカラムにマッピングしました。DBテーブルのカラム名がプロパティ名と同じでよければ、name="name"
の部分は省略できます。マッピング設定の詳細はBasic Mappingを参照してください。
ここで、consoleコマンドを使って、nameプロパティのGetterとSetterを追加します。
$ php bin/console doctrine:generate:entities AppBundle/Entity/Unsei
... class Unsei { ... public function setName($name) { ... } public function getName() { ... } }
GetterとSetterが追加されました。
Getter、Setterの内容は修正しても構いません。console doctrine:generate:entities
コマンドは既に存在するGetter, Setterは上書きしない為、何度でも実行できます。
Entityを生成するコマンドと、GetterとSetterを生成するコマンドが似ているのて注意してください。 doctrine:generate:entity Entityを生成するコマンド doctrine:generate:entities GetterとSetterの生成するコマンド
bin/console
で実行できるコマンド一覧の表示、ヘルプの表示は以下のように行います。
詳細は「consoleコマンド」を参照してください。
$ php bin/console list | grep doctrine:ent generate:doctrine:entities Generates entity classes and method stubs from your mapping information generate:doctrine:entity Generates a new Doctrine entity inside a bundle $ php bin/console generate:doctrine:entities --help Usage: doctrine:generate:entities [options] [--] <name> generate:doctrine:entities Arguments: name A bundle name, a namespace, or a class name
Unseiエンティティが完成したので、その内容でDBテーブルを作成します。
$ php bin/console doctrine:schema:update --force
データーベースの中身を確認してみます。
$ sqlite3 var/data.db3 sqlite> .table unsei sqlite> .schema CREATE TABLE unsei (id INTEGER NOT NULL, name VARCHAR(255) NOT NULL, PRIMARY KEY(id));
Unseiエンティティのマッピング情報から、unseiテーブルを作成できました。
SQLを使って、データを格納します。
sqlite> INSERT INTO unsei (name) VALUES ("大吉"); sqlite> INSERT INTO unsei (name) VALUES ("中吉"); sqlite> INSERT INTO unsei (name) VALUES ("小吉"); sqlite> INSERT INTO unsei (name) VALUES ("末吉"); sqlite> INSERT INTO unsei (name) VALUES ("凶"); sqlite> select * from unsei; id name ---------- ---------- 1 大吉 2 中吉 3 小吉 4 末吉 5 凶
エンティティとレポジトリが出来たので、これらを使うようにアプリケーションを修正します。
まず、Controllerを修正します。
... use AppBundle\Entity\Unsei; // (a) use AppBundle\Repository\UnseiRepository; // (b) class OmikujiController extends Controller { ... public function omikujiAction(Request $request, $yourname) { // $omikuji = ['大吉', '中吉', '小吉', '末吉', '凶']; /** @var UnseiRepository */ $repository = $this->getDoctrine()->getRepository(Unsei::class); // ① $omikuji = $repository->findAll(); // ② $number = rand(0, count($omikuji) - 1); return $this->render('omikuji/omikuji.html.twig', [ 'name' => $yourname, 'unsei' => $omikuji[$number], // ③ ]); } }
① Umsei
エンティティに対応するリポジトリ、すなわちUnseiRepository
を取得しています。
② UnseiRepository
から全てのエンティティを取得しています。ここで返ってくるのはUnsei
エンティティのオブジェクトの配列です。
③ ランダムにピックアップしたUnsei
エンティティをテンプレートに渡します。以前は文字列を渡していましたが、今回はUnsei
エンティティのオブジェクトを渡していることに注意してください。テンプレート内での扱いが違ってきます。
(a)(b)のクラスのインポートもお忘れなく!
次に、Viewを修正します。
{% extends 'base.html.twig' %} {% block title %}おみくじ{% endblock %} {% block body %} {# {{ name }}さんの運勢は {{ unsei }} です。※コメントアウト #} {{ name }}さんの運勢は {{ unsei.name }} です。 {# ① #} {% endblock %}
① 以前は文字列変数としてのunsei
を表示していましたが、今回はunsei
オブジェクトのname
プロパティを表示するように修正しました。twig内で、オブジェクトのプロパティにアクセスするには、“.”(ドット)を使います。
http://localhost:8000/omikuji/Agent_Dunham にアクセスして動作確認を行います。「Agent_Dunhamさんの運勢は XX です」と表示されます。