2011年10月17日月曜日

Model (Doctrine) について②

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

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

オブジェクトの永続化


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

use Acme\StoreBundle\Entity\Product;
use Symfony\Component\HttpFoundation\Response;

public function createAction()
{
    // Productインスタンスの作成
    $product = new Product();
    // 値をセット
    $product->setName('A Foo Bar');
    $product->setPrice('19.99');
    $product->setDescription('Lorem ipsum dolor');
    // EntityManager オブジェクトの取得
    $em = $this->getDoctrine()->getEntityManager();
    // データの保存
    $em->persist($product);
    $em->flush();

    return new Response('Created product id '.$product->getId());
}


オブジェクトのフェッチ


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

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

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

// IDからデータを取得
$product = $repository->find($id);

// 指定したカラムの値からデータを1つ取得
$product = $repository->findOneById($id);
$product = $repository->findOneByName('foo');

// 同様に、指定したカラムの値からデータを取得 (複数)
$products = $repository->findByPrice(19.99);

// 細かい検索条件を付ける場合は以下 (findOneByは1つ、findByは複数取得)
$product = $repository->findOneBy(array('name' => 'foo', 'price' => 19.99));
$product = $repository->findBy(
    array('name' => 'foo'),
    array('price' => 'ASC')
);

// 全て取得
$products = $repository->findAll();

// 自分でクエリーを生成することも簡単
$em = $this->getDoctrine()->getEntityManager();
$query = $em->createQuery(
    'SELECT p FROM AcmeStoreBundle:Product p WHERE p.price > :price ORDER BY p.price ASC'
)->setParameter('price', '19.99');

$products = $query->getResult();

// クエリービルダーを使用することもできる (createQueryBuilder)
$repository = $this->getDoctrine()
    ->getRepository('AcmeStoreBundle:Product');

$query = $repository->createQueryBuilder('p')
    ->where('p.price > :price')
    ->setParameter('price', '19.99')
    ->orderBy('p.price', 'ASC')
    ->getQuery();

$products = $query->getResult();



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


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

public function updateAction($id)
{
    // データを取得
    $em = $this->getDoctrine()->getEntityManager();
    $product = $em->getRepository('AcmeStoreBundle:Product')->find($id);
    if (!$product) {
        throw $this->createNotFoundException('No product found for id '.$id);
    }
    
    // データに値をセット
    $product->setName('New product name!');
    // データを更新
    // $productの中身を変更して、そのまま flush() すれば更新される。(参照渡しでエンティティを取得しているっぽいね。)
    // よって、persist() とかいちいち呼ぶ必要が無いです。
    $em->flush();

    // 削除はこうやる
    $em->remove($product);
    $em->flush();

    return $this->redirect($this->generateUrl('homepage'));
}


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


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

まず、ProductRepository を使いますよーと、アノテーションで記載する。
// src/Acme/StoreBundle/Entity/Product.php
namespace Acme\StoreBundle\Entity;

use Doctrine\ORM\Mapping as ORM;

/**
 * @ORM\Entity(repositoryClass="Acme\StoreBundle\Repository\ProductRepository")
 */
class Product
{
    //...
}

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

php app/console doctrine:generate:entities Acme

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

// src/Acme/StoreBundle/Repository/ProductRepository.php
namespace Acme\StoreBundle\Repository;

use Doctrine\ORM\EntityRepository;

class ProductRepository extends EntityRepository
{
    public function findAllOrderedByName()
    {
        return $this->getEntityManager()
            ->createQuery('SELECT p FROM AcmeStoreBundle:Product p ORDER BY p.name ASC')
            ->getResult();
    }
}

0 コメント:

コメントを投稿

Share

Twitter Delicious Facebook Digg Stumbleupon Favorites More