在doctrine2中使用事务性方法进行显式事务处理


Explicit transaction in doctrine2 using transactional method

我尝试使用EntityManager::transactional(function($em) {});方法实现简单的表单处理。看起来很简单,但问题是:我如何将附加值传递给这样的实现?确切地说,我想做以下操作

$em  = $this->getServiceLocator()->get('Doctrine'ORM'EntityManager');
$request = $this->getRequest();
$form = new BugForm();
$form->get('reporter')->setValueOptions(
    $em->getRepository('Application'Entity'Person')->getPersonListArray()
);
$form->get('engineer')->setValueOptions(
    $em->getRepository('Application'Entity'Person')->getPersonListArray()
);
$form->get('products')->setValueOptions(
    $em->getRepository('Application'Entity'Product')->getProductListArray()
);
$confirmation = "";
if($request->isPost()) {
    $em->transactional(function($em) {
        $form = new BugForm();
        $request = $this->getRequest();
        $form->setData($request->getPost());
        if($form->isValid()) {
            $form = new BugForm();
            $hydrator = new DoctrineHydrator($em);
            $data = $form->getData();
            $data['created'] = time();
            $data['status'] = 'OPEN';
            $bug = $hydrator->hydrate($data, new Bug());
            $em->persist($bug);
            $em->flush();
            $confirmation = "Created bug with ID ".$bug->getId()."<br/>";
        }
    });
}
return array(
    'form'         => $form,
    'confirmation' => $confirmation
);

问题是匿名函数中的this->getRequest()调用不创建数据,因此我无法填充BugForm对象。当然,我可以在这里使用超全局_POST数组但它似乎不对。

要在匿名函数中使用$this,您需要使用PHP 5.4或更高版本。您还可以通过使用use语言结构使父作用域的$request在闭包作用域中可用来解决问题,如下所示:

$em->transactional(function($em) use ($request) {
    $form = new BugForm();
    $form->setData($request->getPost());
    if($form->isValid()) {
        $form = new BugForm();
        $hydrator = new DoctrineHydrator($em);
        $data = $form->getData();
        $data['created'] = time();
        $data['status'] = 'OPEN';
        $bug = $hydrator->hydrate($data, new Bug());
        $em->persist($bug);
        $em->flush();
        $confirmation = "Created bug with ID ".$bug->getId()."<br/>";
    }
});

还应该注意,闭包中的$confirmation变量与父函数中返回的$confirmation变量处于不同的作用域。为了修改父作用域中的$confirmation变量,您应该在闭包作用域中通过引用使其可用:

$em->transactional(function($em) use ($request, &$confirmation) {