【问题标题】:Doctrine2: calling flush multiple timesDoctrine2:多次调用flush
【发布时间】:2015-10-08 09:03:24
【问题描述】:

我对 Symfony 2.3 上的 Doctrine 和实体有疑问。

根据 v2.3 "Documentation Book" 章节 "Databases and Doctrine" > Saving Related Entities,该示例同时在 product 中创建一个新行和category 表格并将 product.category_id 值与新类别 项的id 关联。

问题在于控制器操作在任何时候都会创建一个新的Product和一个新的Category

为了创建一个新的产品并将其category_id与现有的类别 id相关联,这是routing.yml强> 路线:

acme_store_create_product_by_category:
path:     /create/newproduct/{name}/{categoryId}
defaults: { _controller: AcmeStoreBundle:Default:createProduct }

我做了一个通过 URL 传递参数的测试:
/web/store/create/newproduct/Kayak/12

我做了这样的事情,看起来工作正常:

public function createProductAction($name, $categoryId)
{
    $em = $this->getDoctrine()->getManager();

    if ( $em->getRepository("AcmeStoreBundle:Category")->findOneById($categoryId) ) {

        $product = new Product();

        $product->setName($name);
        $product->setPrice(220);
        $product->setDescription("This is just a test");

        $em->persist($product);

        $em->flush();

        $newproduct = $em->getRepository("AcmeStoreBundle:Product")->find($product->getId());
        /** Create new product and populate $newproduct with its data */


        $repository = $em->getRepository("AcmeStoreBundle:Category")->find($categoryId);

        $newproduct->setCategory($repository);

        $em->persist($newproduct);

        $em->flush();
        /** Update the id_category field of the new product with parameter $categoryId */

        //exit(\Doctrine\Common\Util\Debug::dump($product));

        return new Response('Create product ' . $name . ' with category id ' . $categoryId);

    } else {

        return new Response('It doesn\'t exists any category with id ' . $categoryId);
    }
}

在这种情况下我的疑问是:在同一个 action 中调用 flush() 方法两次是一个好习惯吗?在这种情况下,我想创建一个新的product,从“列表框”中选择相关的category

提前谢谢你!

【问题讨论】:

    标签: php symfony doctrine-orm doctrine


    【解决方案1】:

    我认为这主要取决于您的应用程序域。如果您运行flush 两次,则意味着您正在运行两个事务。在第一个中,您保留了一个产品,在第二个中,您保留了一个类别。因此,如果第一个事务失败(假设您在产品名称上有一个唯一键,并且您尝试保留具有相同名称的产品,因此您会遇到重复键异常),然后问问自己是否可以继续并坚持一个类别。我认为我们不能在这里轻易回答,因为我认为这取决于您的应用程序逻辑、该端点应该做什么、如果您最终拥有一个产品而不是一个类别会发生什么,反之亦然。

    您还应该考虑,如果您在第一个事务中遇到异常,您的代码将无法处理该错误,因此第二个事务将失败。当出现重复键之类的异常时,所有实体都将被分离,并且实体管理器不再知道如何管理事物。所以你必须重置它,否则你会遇到EntityManager is closed 问题。

    try {
        // first transaction
        $entityManager->persist($entityOne);
        $entityManager->flush();
    } catch (\Exception $e) {
        /* ... handle the exception */ 
        $entityManager->resetManager();
    }
    
    // now we can safely run a second transaction here
    

    我希望这能回答你的问题:-)

    【讨论】:

    • 非常感谢弗朗西斯科 :-) !我目前正在努力打开类似实体的方法和 ORM。它与 PDO 或 mysqli 库方法相去甚远。是的,我发布的示例只是我的好奇心,与 Symfony 文档手册中的示例严格相关,当然不是真正的应用程序 :-) 无论如何,您的提示非常有用!我将在我的测试代码中实现它,以便为将来的情况记住
    • 很高兴它帮助了@FabrizioSabato :-) 您还在寻找其他信息吗?我问是因为我不确定这是否完全回答了你的问题。最好更改问题标题,以便对来自搜索引擎的用户也有用。像“Doctrine2:多次调用flush”之类的东西?
    • 好吧,现在我正在阅读一些关于网络表单和与之相关的行为的文档。我很确定这会带来更多信息,我很乐意在这次讨论中分享这些信息。好的,按照你的建议我改一下标题。
    • 如果这回答了您的问题,您应该将其标记为已接受的答案:)
    【解决方案2】:

    我建议编辑后的代码sn-p。

        public function createProductAction($name, $categoryId)
        {
            $em = $this->getDoctrine()->getManager();
        
            if ( $em->getRepository("AcmeStoreBundle:Category")->findOneById($categoryId) ) {
        
                $repository = $em->getRepository("AcmeStoreBundle:Category")->find($categoryId);
        
                $product = new Product();
                $product->setName($name);
                $product->setPrice(220);
                $product->setDescription("This is just a test");
                $product->setCategory($repository);
        
                $em->persist($product);
                $em->flush();
        
                return new Response('Create product ' . $name . ' with category id ' . $categoryId);
        
            } else {
        
                return new Response('It doesn\'t exists any category with id ' . $categoryId);
            }
        }
    

    【讨论】:

      猜你喜欢
      • 2013-09-10
      • 2013-11-23
      • 2023-03-18
      • 2014-02-21
      • 1970-01-01
      • 1970-01-01
      • 2015-05-02
      • 1970-01-01
      • 2017-12-15
      相关资源
      最近更新 更多