php Symfony2 - Doctrine - 有没有办法在一行中保存实体?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/12019839/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-25 02:39:42  来源:igfitidea点击:

Symfony2 - Doctrine - Is there any way to save entity in one line?

phpsymfonydoctrine-orm

提问by redexp

To save entity with doctrine I should do like this

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

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

But maybe I can somehow do that in one line like

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

$product->save();

or

或者

$this->saveEntity($product);

or

或者

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

If I need to create this methods by my self then how to do that in symfony way?

如果我需要自己创建这些方法,那么如何以 symfony 的方式做到这一点?

回答by Mun Mun Das

Well persist()and flush()are totally different and independent operation. When you persist an entity object you are telling the entity manager to track changes of the object. When you call flush()method the entity manager will push the changes of the entity objects the entity manager tracks to the database in single transaction. Most of the time entity manager have to manage multiple object. For example besides your productentity you may also have to track tagor cartentity. Calling persistAndFlush()every time when you save those entity object will cause multiple IO connection to DB. Which is not efficient. So I think it is better to treat them as a separate operation.

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

回答by Pete Mitchell

If you are using the controller in the framework bundle, and writing your persistence logic in your controllers, you could extend Symfony\Bundle\FrameworkBundle\Controller\Controllerwith the following

如果您在框架包中使用控制器,并在控制器中编写持久性逻辑,则可以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();
    }
}

In all of your other controllers, you would then extend your ExampleNameSpace\Controller\BaseControllerinstead of the one from the Symfony Frameworkbundle.

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

Alternatively, and the approach I take, is to write a manager class for each entity that has the class name and the doctrine entity manager injected. Each manager class extends an abstract manager class with the following methods:

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

<?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;
    }
}

The managers are configured in the dependency injection container, with the appropriate class for the entity, and provide access to creating, saving and deleting the entity they are responsible for, as well as accessing the repository.

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

One would create an entity in a controller with the manager as following:

可以在控制器中使用经理创建一个实体,如下所示:

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);
    }
}

回答by T-Rex

I know your desire. At the first time a single save method looks nice.

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

But if you have 2 methods you are able to collect the statements before sending them to the database. Thats not the actual work of doctrine i guess, but maybe with an update you can use flush("together"). On this way you can save a lot of overhead.

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

回答by Илья Зеленько

Based on this post(it's written about it at the very end) you can write the save code to the repository:

基于这篇文章(它是在最后写的),您可以将保存代码写入存储库:

class DoctrineORMCustomerRepository extends EntityRepository implements CustomerRepository
{
    public function save(Customer $customer)
    {
        $this->_em->persist($customer);
        $this->_em->flush();
    }
}