2

With propel we have findOneOrCreate()

Example.

$bookTag = BookTagQuery::create()
->filterByBook($book)
->findOneOrCreate();   

In doctrine anywhere in the controller We can do something like that.

...................
       $filename='something';
       $document_exists = $em->getRepository('DemoBundle:Document')
                ->findOneBy(array('filename' => $filename));

        if (null === $document_exists) {
            $document = new Document();
            $document->setFilename($filename);
            $em->persist($document);
            $em->flush();
        }    

Is there another way to achieve this in Doctrine?

Is it OK to call the Entity Manager inside the Entity Repository? Any suggestions?

4

2 回答 2

4

最简单的方法是扩展基础存储库:

// src/Acme/YourBundle/Entity/YourRepository.php
namespace Acme\YourBundle\Entity;

use Doctrine\ORM\EntityRepository;

class YourRepository extends EntityRepository
{
    public function findOneOrCreate(array $criteria)
    {
        $entity = $this->findOneBy($criteria);

        if (null === $entity)
        {
           $entity = new $this->getClassName();
           $entity->setTheDataSomehow($criteria); 
           $this->_em->persist($entity);
           $this->_em->flush();
        }

        return $entity
    }
}

然后告诉您的实体使用此存储库或进一步扩展特定实体:

// src/Acme/StoreBundle/Entity/Product.php
namespace Acme\StoreBundle\Entity;

use Doctrine\ORM\Mapping as ORM;

/**
 * @ORM\Entity(repositoryClass="Acme\YourBundle\Entity\YourRepository")
 */
class Product
{
    //...
}

并在您的控制器中使用它:

$em = $this->getDoctrine()->getManager();
$product = $em->getRepository('AcmeStoreBundle:Product')
              ->findOrCreate(array('foo' => 'Bar'));

来源:http ://symfony.com/doc/current/book/doctrine.html#custom-repository-classes

请注意flush存储库中的这一点,因为它会以这种方式刷新 EntityManager 中所有未保存的更改。

于 2013-07-30T07:43:27.717 回答
0

看看Doctrine\ORM\Repository 这里的构造函数。

EntityManager是构建存储库所必需的。默认情况下,管理器不能直接从存储库对象访问,因为属性_em和 getter 函数getEntityManagerprotected

EntityManager但是...是的,确定通过_em存储库内的属性调用该属性是“可以的” 。所有其他方法,如findBy,......等也使用它并且需要实体管理器实际工作:)

/**
 * @var EntityManager
 */
protected $_em;

public function __construct($em, Mapping\ClassMetadata $class)
{
    $this->_entityName = $class->name;
    $this->_em         = $em;
    $this->_class      = $class;
}

/**
 * @return EntityManager
 */
protected function getEntityManager()
{
    return $this->_em;
}

您可以轻松地将findOneOrCreate方法添加到实体存储库或创建包含该方法的通用扩展存储库。

然后,您可以在需要具体实体存储库中的方法时扩展这个新的基础存储库。

于 2013-07-29T23:34:01.090 回答