2011年10月17日月曜日

Model (Doctrine) について②

Model (Doctrine) について① の続きです。

詳しくは、Databases and Doctrine ("The Model")を参照してください。

オブジェクトの永続化


INSERTするときは以下のように、Entityに値をセットし、EntituManagerのpersist()を呼び、最後にflush() を実行すれば良い。

  1. use Acme\StoreBundle\Entity\Product;  
  2. use Symfony\Component\HttpFoundation\Response;  
  3.   
  4. public function createAction()  
  5. {  
  6.     // Productインスタンスの作成  
  7.     $product = new Product();  
  8.     // 値をセット  
  9.     $product->setName('A Foo Bar');  
  10.     $product->setPrice('19.99');  
  11.     $product->setDescription('Lorem ipsum dolor');  
  12.     // EntityManager オブジェクトの取得  
  13.     $em = $this->getDoctrine()->getEntityManager();  
  14.     // データの保存  
  15.     $em->persist($product);  
  16.     $em->flush();  
  17.   
  18.     return new Response('Created product id '.$product->getId());  
  19. }  


オブジェクトのフェッチ


Doctrineオブジェクトからフェッチ対象のリポジトリを取得 (getRepository) する。
そのリポジトリオブジェクトに対し、 find, findAll, findBy などでデータを取得できる。

  1. $product = $this->getDoctrine()  
  2.     ->getRepository('AcmeStoreBundle:Product')  
  3.     ->find($id);  

いろんな取得方法がある。

  1. // IDからデータを取得  
  2. $product = $repository->find($id);  
  3.   
  4. // 指定したカラムの値からデータを1つ取得  
  5. $product = $repository->findOneById($id);  
  6. $product = $repository->findOneByName('foo');  
  7.   
  8. // 同様に、指定したカラムの値からデータを取得 (複数)  
  9. $products = $repository->findByPrice(19.99);  
  10.   
  11. // 細かい検索条件を付ける場合は以下 (findOneByは1つ、findByは複数取得)  
  12. $product = $repository->findOneBy(array('name' => 'foo''price' => 19.99));  
  13. $product = $repository->findBy(  
  14.     array('name' => 'foo'),  
  15.     array('price' => 'ASC')  
  16. );  
  17.   
  18. // 全て取得  
  19. $products = $repository->findAll();  
  20.   
  21. // 自分でクエリーを生成することも簡単  
  22. $em = $this->getDoctrine()->getEntityManager();  
  23. $query = $em->createQuery(  
  24.     'SELECT p FROM AcmeStoreBundle:Product p WHERE p.price > :price ORDER BY p.price ASC'  
  25. )->setParameter('price''19.99');  
  26.   
  27. $products = $query->getResult();  
  28.   
  29. // クエリービルダーを使用することもできる (createQueryBuilder)  
  30. $repository = $this->getDoctrine()  
  31.     ->getRepository('AcmeStoreBundle:Product');  
  32.   
  33. $query = $repository->createQueryBuilder('p')  
  34.     ->where('p.price > :price')  
  35.     ->setParameter('price''19.99')  
  36.     ->orderBy('p.price''ASC')  
  37.     ->getQuery();  
  38.   
  39. $products = $query->getResult();  


オブジェクトのアップデートと削除


データをアップデート処理と削除処理について。
ちなみに、update, delete, どちらも最後に flush() を呼ぶ必要があります。

  1. public function updateAction($id)  
  2. {  
  3.     // データを取得  
  4.     $em = $this->getDoctrine()->getEntityManager();  
  5.     $product = $em->getRepository('AcmeStoreBundle:Product')->find($id);  
  6.     if (!$product) {  
  7.         throw $this->createNotFoundException('No product found for id '.$id);  
  8.     }  
  9.       
  10.     // データに値をセット  
  11.     $product->setName('New product name!');  
  12.     // データを更新  
  13.     // $productの中身を変更して、そのまま flush() すれば更新される。(参照渡しでエンティティを取得しているっぽいね。)  
  14.     // よって、persist() とかいちいち呼ぶ必要が無いです。  
  15.     $em->flush();  
  16.   
  17.     // 削除はこうやる  
  18.     $em->remove($product);  
  19.     $em->flush();  
  20.   
  21.     return $this->redirect($this->generateUrl('homepage'));  
  22. }  


カスタムなリポジトリクラスの作成


前述のように、自分でクエリーを作成 (createQuery) する場合を考える。そのとき、毎回同じコードをコントローラに記述する事になってしまうと煩雑になってしまう。そんなときは、自分でカスタムなリポジトリクラスを作成することで解決できる。

まず、ProductRepository を使いますよーと、アノテーションで記載する。
  1. // src/Acme/StoreBundle/Entity/Product.php  
  2. namespace Acme\StoreBundle\Entity;  
  3.   
  4. use Doctrine\ORM\Mapping as ORM;  
  5.   
  6. /** 
  7.  * @ORM\Entity(repositoryClass="Acme\StoreBundle\Repository\ProductRepository") 
  8.  */  
  9. class Product  
  10. {  
  11.     //...  
  12. }  

....で、以下のコマンドを実行する

php app/console doctrine:generate:entities Acme

そうすると、リポジトリクラスが作成される(以下)
そこにfindAllOrderedByNameなどのカスタムなプログラムを書いてやる。これでOK。

  1. // src/Acme/StoreBundle/Repository/ProductRepository.php  
  2. namespace Acme\StoreBundle\Repository;  
  3.   
  4. use Doctrine\ORM\EntityRepository;  
  5.   
  6. class ProductRepository extends EntityRepository  
  7. {  
  8.     public function findAllOrderedByName()  
  9.     {  
  10.         return $this->getEntityManager()  
  11.             ->createQuery('SELECT p FROM AcmeStoreBundle:Product p ORDER BY p.name ASC')  
  12.             ->getResult();  
  13.     }  
  14. }  

0 コメント:

コメントを投稿

Share

Twitter Delicious Facebook Digg Stumbleupon Favorites More