11

为了用教义拯救实体,我应该这样做

$em = $this->getDoctrine()->getEntityManager();
$em->persist($product);
$em->flush();

但也许我可以以某种方式在一行中做到这一点

$product->save();

或者

$this->saveEntity($product);

或者

$this->getDoctrineEntityManager()->persistAndFlush($product);

如果我需要自己创建这些方法,那么如何以 symfony 的方式实现呢?

4

4 回答 4

17

persist()flush()是完全不同的和独立的操作。当您持久化实体对象时,您是在告诉实体管理器跟踪对象的更改。当您调用flush()方法时,实体管理器将在单个事务中将实体管理器跟踪的实体对象的更改推送到数据库。大多数时候实体管理器必须管理多个对象。例如,除了您的product实体之外,您可能还必须跟踪tagcart实体。persistAndFlush()每次保存这些实体对象时调用都会导致多个 IO 连接到 DB。这不是有效的。所以我认为最好将它们视为单独的操作。

于 2012-08-18T17:58:20.657 回答
11

如果您在框架包中使用控制器,并在控制器中编写持久性逻辑,则可以Symfony\Bundle\FrameworkBundle\Controller\Controller使用以下内容进行扩展

namespace ExampleNameSpace\Controller;

use Symfony\Bundle\FrameworkBundle\Controller\Controller;

class BaseController extends Controller
{
    public function persistAndSave($entity)
    {
        $em = $this->getDoctrine()->getEntityManager();
        $em->persist($entity);
        $em->flush();
    }
}

在所有其他控制器中,您将扩展您的ExampleNameSpace\Controller\BaseController而不是来自 Symfony Frameworkbundle 的控制器。

或者,我采用的方法是为每个具有类名和注入的学说实体管理器的实体编写一个管理器类。每个管理器类都使用以下方法扩展一个抽象管理器类:

<?php

abstract class AbstractManager
{
    /**
     * The Entity Manager
     *
     * @var \Doctrine\ORM\EntityManager  The Doctrine Entity Manager
     */
    protected $em;

    /**
     * The full class path associated with the repository
     *
     * @var string
     */
    protected $class;

    /**
     * The repository for the manager
     *
     * @var \Doctrine\ORM\EntityRepository
     */
    protected $repository;

    /**
     * Creates a new instance of the primary class managed by a given
     * manager
     *
     * @return object       A new instance of the entity being managed
     */
    public function create()
    {
        return new $this->class();
    }

    /**
     * {@inheritDoc}
     */
    public function save($object, $flush = false)
    {
        if( ! $this->supportsClass($object))
        {
            throw new \InvalidArgumentException(sprintf('Invalid entity passed to this manager, expected instance of %s', $this->class));
        }

        $this->em->persist($object);

        if($flush === true)
        {
            $this->flush();
        }

        return $object;
    }

    /**
     * {@inheritDoc}
     */
    public function delete($object, $flush = false)
    {
        if( ! $this->supportsClass($object))
        {
            throw new \InvalidArgumentException(sprintf('Invalid entity passed to this manager, expected instance of %s', $this->class));
        }

        $this->em->remove($object);

        if($flush === true)
        {
            $this->flush();
        }

        return true;
    }

    /**
     * Convenience method providing access to the entity manager flush method
     */
    public function flush()
    {
        $this->em->flush();
    }

    /**
     * {@inheritDoc}
     */
    public function supportsClass($object)
    {
        return $object instanceof $this->class || is_subclass_of($object, $this->class);
    }

    /**
     * Set class. Setter for dependency injection
     *
     * @param object $class  A class related to this manager
     */
    public function setClass($class)
    {
        $this->class = $class;
    }

    /**
     * Set entity manager. Setter for dependency injection
     *
     * @param \Doctrine\ORM\EntityManager $entity_manager
     */
    public function setEntityManager(\Doctrine\ORM\EntityManager $entity_manager)
    {
        $this->em = $entity_manager;
    }

    /**
     * Returns the repository
     *
     * @return \Doctrine\ORM\EntityRepository    A Doctrine Repository for the
     *                                          class related to this Manager
     */
    protected function getRepository()
    {
        if( ! $this->repository)
        {
            $this->repository = $this->em->getRepository($this->class);
        }

        return $this->repository;
    }
}

管理器在依赖注入容器中配置,具有实体的适当类,并提供创建、保存和删除他们负责的实体的访问权限,以及访问存储库的权限。

可以在具有管理器的控制器中创建一个实体,如下所示:

public function createAction(Request $request)
{
    $entityManager = $this->get('some.entity.manager');

    $entity = $entityManager->create();

    $form = $this->createForm(new EntityForm(), $entity);

    $form->bindRequest($request);

    if($form->isValid())
    {
        $entityManager->save($entity, true);
    }
}
于 2012-08-18T16:15:43.893 回答
1

我知道你的愿望。第一次,单个保存方法看起来不错。

但是,如果您有 2 种方法,则可以在将语句发送到数据库之前收集它们。我猜这不是教义的实际工作,但也许通过更新你可以使用flush(“together”)。通过这种方式,您可以节省大量开销。

于 2016-02-01T00:20:03.720 回答
1

根据这篇文章(最后写了它),您可以将保存代码写入存储库:

class DoctrineORMCustomerRepository extends EntityRepository implements CustomerRepository
{
    public function save(Customer $customer)
    {
        $this->_em->persist($customer);
        $this->_em->flush();
    }
}
于 2019-02-01T11:20:06.917 回答