こんにちは!@mrtryです。
最近、つくりおきした鍋を冷蔵庫に入れ忘れて、おかずを腐らせる失態を2度ほど犯しています...。
みなさん...。最近暖かくなってきていますので、食中毒には気を付けましょう...。
さて、「Symfony2入門」の8回目の記事です。
前回のSymfony2で利用されているDoctrineに入門する(中編)に引き続き、今日は後編をお送りします。
前回は、DoctrineとDBを連携するための設定
エンティティの作成
エンティティを元したテーブル作成
を紹介しました。
今回は、 Doctrineを介したCRUD操作
について紹介したいと思います。
Create
Createする際の手順は以下のようになります。
- EntityManagerを準備する
- エンティティを新しく生成する
- EntityManagerを介して、生成したエンティティをDoctrineの管理下におく
- DBに永続化する
以下は、実際のコードの例です。
use AppBundle\Entity\Product; public function createAction() { // EntityManagerを準備する $em = $this->getDoctrine()->getManager(); // 新しいエンティティを作成し、プロパティを設定する $product = new Product(); $product->setName('Apple'); $product->setPrice(100); $product->setDescription('From Aomori'); // $productを永続化するエンティティとして管理する $em->persist($product); // DBへ永続化する $em->flush(); ... }
順に見ていきましょう。
// EntityManagerを取得する $em = $this->getDoctrine()->getManager();
EntityManager
というものが出てきました。
EntityManagerとは、エンティティの情報をDBへ永続化してくれるもの
です。
エンティティの情報をDBへ永続化する際は、このEntityManegerを介して行うことになります。
なお、今回はRDBとしてmysqlを用いているので、EntityManagerが返ってきますが、 MongoDBなどのドキュメント指向データベースを用いた際は、DocumentManagerが返ってきます。
// 新しいエンティティを作成し、プロパティを設定する $product = new Product(); $product->setName('Apple'); $product->setPrice(100); $product->setDescription('From Aomori');
前回生成したProductエンティティを新しく生成し、各セッターを用いてプロパティを設定しています。
// $productを永続化するエンティティとして管理する $em->persist($product); // DBへ永続化する $em->flush();
EntityManegerを介して、DBにエンティティの内容を反映します。 まず、
$em->persist($product);
で、引数で渡されたエンティティを永続化するエンティティ
としてDoctrineで管理します。
persist
という名前を見て「これで永続化されるのかな?」と勘違いしてしまうかもしれませんが、
あくまで管理しているだけ
で、まだDBへの永続化処理は行われていません。
その後、
$em->flush();
を行うと、それまでにpersist()
されていたエンティティがDBへ永続化されます。
Read
Readする際の手順は、以下のようになります。
- 読み取りたいエンティティのリポジトリを準備する
- リポジトリのfind系メソッドを用いて、エンティティを取得する
以下は、実際のコードの例です。
public function readAction() { // ProductRepositoryを取得 $productRepository = $this->getDoctrine()->getRepository('AppBundle:Product'); // productテーブルにあるカラム`name`について、`Apple`という文字列に一致するエンティティを取得する $product = $productRepository->findByName('Apple'); ... }
順に見ていきましょう。
// ProductRepositoryを取得 $productRepository = $this->getDoctrine()->getRepository('AppBundle:Product');
今度は、ProductRepository
というものが出てきました。
このリポジトリ
とは、DBのテーブルをオブジェクトとしたものです。
エンティティの永続化はEntityManagerを介して行いますが、
エンティティを取得するときは、このリポジトリを介して取得します。
// productテーブルにあるカラム`name`について、`Apple`という文字列に一致するエンティティを取得する
$product = $productRepository->findByName('Apple');
$productRepository
のfindByName()
を用いて、
productテーブルにあるカラムname
について、Apple
という文字列に一致するエンティティを取得します。
このように、エンティティを取得するは、Repositoryに実装されているfindXXX
と名前についたメソッドを用いて取得します。
以下で、その他のfind系メソッドの例を紹介します
参考:Fetching Objects from the Database
// 主キーで検索し、一致するエンティティを取得する (普通はID) $product = $repository->find($productId); // 任意のカラム名に基づき、任意の値で検索し、該当するうちの最初のエンティティを取得 $product = $repository->findOneById($productId); $product = $repository->findOneByName('Keyboard'); // 任意のカラム名に基づき、任意の値を検索し、一致するエンティティをすべて取得する $products = $repository->findByPrice(19.99); // すべてのエンティティを取得 $products = $repository->findAll();
Update
Updateする際の手順は、以下のようになります。
- リポジトリを介して、更新対象とするエンティティを取得する
- 取得したエンティティのプロパティを更新する
- DBへ永続化する
以下は、実際のコードの例です。
use AppBundle\Entity\Product; public function updateAction() { // EntityManagerを取得する $em = $this->getDoctrine()->getManager(); $productId = XXX; // productテーブルからIDを指定してエンティティを取得する $product = $this->getDoctrine() ->getRepository('AppBundle:Product') ->find($productId); // priceに`100`をセットする $product->setPrice(100); // DBへ永続化する $em->flush(); ... }
CreateとReadで紹介したメソッドの組み合わせで実現できますが、1箇所だけ違うところがあります。
DBへの永続化の過程で、persist()
が省略されています。
persist()
はDoctrine側でこのエンティティを管理するよ
という意味で実行するものでした。
ですが、上記のコードのように、Repositoryを介して取得したエンティティについては、既にDoctrine側の管理対象となっているので、書かなくても良いです。
Notice that calling $em->persist($product) isn't necessary. Recall that this method simply tells Doctrine to manage or "watch" the $product object. In this case, since you fetched the $product object from Doctrine, it's already managed.
Delete
Updateする際の手順は、以下のようになります。
- リポジトリを介して削除対象とするエンティティを取得する。
EntityManager->remove()
を行い、削除するエンティティとして管理する- DBへ永続化する
以下は、実際のコードの例です。
use AppBundle\Entity\Product; public function deleteAction() { // EntityManagerを取得する $em = $this->getDoctrine()->getManager(); // productテーブルからIDを指定してエンティティを取得する $product = $this->getDoctrine() ->getRepository('AppBundle:Product') ->find($productId); //$productを削除するエンティティとして管理する $em->remove($product); // DBへ永続化する $em->flush(); }
エンティティを削除する際は、EntityManagerで用意されているremove()
というメソッドを利用します。
remove()
の引数となるエンティティは、実行したタイミングでDoctrineで管理されるので、flush()
を行うと、DBへ永続化されます。
Doctrine Query Language(DQL)
複数のテーブルを組み合わせたクエリを発行する時、上記の手法だとなかなか難しいこともあります。
今回は詳しく紹介しませんが、DoctrineにはObject Query Language(OQL)として、Doctrine Query Language(DQL)
というものも実装されています。
おわりに
今回は、DoctrineでCRUDをする例を紹介しました。
次回は、サービスコンテナについて紹介したいと思います。
また、この記事は、@mrtryの勉強の一環で書いていますので、 お気づきの点などがありましたら、コメント等でご指摘いただければ幸いです!