交易不适用于子功能

时间:2017-08-01 13:20:10

标签: php laravel laravel-5 transactions

我在Laravel中使用DB::beginTransaction(),但它只适用于在main函数中完成的数据库更改,而不适用于子函数。

主要功能代码:

try {
    DB::beginTransaction();
    $data = array(
        'id' => Input::get('id'),
        'task_title' => Input::get('task_title'),
    );
    DB::table('task')->insert($data);
    $id = DB::getPdo()->lastInsertId();

    // Add Actionees
    if (!$this->addActionees(Input::get('actionees'), $id)) {
        DB::rollback();
        return Response::json(false);
    }
    DB::commit();
    return Response::json(true);
} catch (Exception $ex) {
    DB::rollback();
    return Response::json($ex);
}

子功能代码:

private function addActionees($actionees, $id, $status) {
    try {
        DB::table('task_assignee_user')->where('task_id', $id)->delete(); 
        foreach ($actionees as $act) {
            $actAdd = array(
                'task_id' => $id,
                'user_id' => $act->user_id,
            );
            DB::table('task_assignee')->insert($actAdd);
        }
        return True;
    } catch (Exception $ex) {
        return FALSE;
    }
}

因此,在上面的示例中,在函数addActionees()下完成的更改不会回滚,在函数addActionees()中,在插入新记录之前,将删除所有针对ID的记录。如果发现异常,那么我想恢复这些更改。

5 个答案:

答案 0 :(得分:1)

如果将整个事务包装在一个闭包中 - it will handle everything for you

public mainFunction()
{
    try {
        DB::transaction(function() {
            $id = DB::table('task')->insertGetId(['id' => Input::get('id'),
                                                  'task_title' => Input::get('task_title')]);

            DB::table('task_assignee_user')->where('task_id', $id)->delete(); 

            foreach(Input::get('actionees') as $act) {
                DB::table('task_assignee')->insert(['task_id' => $id,
                                             'user_id' => $act->user_id]);
            }
        });
    } catch (\Exception $e) {
         return Response::json($e);
    }

    return Response::json(true);
}

P.S。我也重构了你的代码,因为它让我疯狂。这应该有用,但我还没有测试过 - 但你得到了一般的想法。

答案 1 :(得分:1)

您不应该在addActionees()方法中捕获异常。只需抛出它,外部的try-catch块就可以处理它:

主要功能代码:

try {
  DB::beginTransaction();
  $data = array(
    'id' => Input::get('id'),
    'task_title' => Input::get('task_title'),
  );
  DB::table('task')->insert($data);
  $id = DB::getPdo()->lastInsertId();

  // Add Actionees
  $this->addActionees(Input::get('actionees'), $id);
  DB::commit();
  return Response::json(true);
} catch (Exception $ex) {
  DB::rollback();
  return Response::json($ex);
}

子功能代码:

private function addActionees($actionees, $id, $status) {
        DB::table('task_assignee_user')->where('task_id', $id)->delete(); 
        foreach ($actionees as $act) {
            $actAdd = array(
                'task_id' => $id,
                'user_id' => $act->user_id,
            );
            DB::table('task_assignee')->insert($actAdd);
        }
}

答案 2 :(得分:0)

在主要功能中:beginTransaction bofore try{

DB::beginTransaction();
try {
$data = array(
...

答案 3 :(得分:0)

它仅适用于在子函数中使用import { Component, OnInit } from '@angular/core'; import { NgbModalRef } from '@ng-bootstrap/ng-bootstrap'; import { JhiEventManager } from 'ng-jhipster'; import { Account, LoginModalService, Principal } from '../shared'; import {Router} from '@angular/router'; @Component({ selector: 'jhi-home', templateUrl: './home.component.html', styleUrls: [ 'home.css' ] }) export class HomeComponent implements OnInit { account: Account; modalRef: NgbModalRef; constructor( private principal: Principal, private loginModalService: LoginModalService, private eventManager: JhiEventManager, private router: Router, ) { } ngOnInit() { this.principal.identity().then((account) => { this.account = account; }); this.registerAuthenticationSuccess(); } registerAuthenticationSuccess() { this.eventManager.subscribe('authenticationSuccess', (message) => { this.principal.identity().then((account) => { this.account = account; // The redirection to /admin this.principal.hasAnyAuthority(['ROLE_ADMIN']).then((result) => { if (result) { this.router.navigate(['/admin']); } }); }); }); } isAuthenticated() { return this.principal.isAuthenticated(); } login() { this.modalRef = this.loginModalService.open(); } } ,但它不是我的问题的答案:

主要功能代码:

DB::beginTransaction()

子功能代码:

try {
  DB::beginTransaction();
  $data = array(
    'id' => Input::get('id'),
    'task_title' => Input::get('task_title'),
  );
  DB::table('task')->insert($data);
  $id = DB::getPdo()->lastInsertId();

  // Add Actionees
  if (!$this->addActionees(Input::get('actionees'), $id)) {
    DB::rollback();
    return Response::json(false);
  }
  DB::commit();
  return Response::json(true);
} catch (Exception $ex) {
  DB::rollback();
  return Response::json($ex);
}

答案 4 :(得分:0)

尝试通过以下流程使用事务:

DB::beginTransaction();
try {
    $data = array(
        'id' => Input::get('id'),
        'task_title' => Input::get('task_title'),
    );
    DB::table('task')->insert($data);
    $id = DB::getPdo()->lastInsertId();

    // Add Actionees
    $this->addActionees(Input::get('actionees'), $id);
} catch (Exception $ex) {
    DB::rollBack();
    return Response::json($ex);
}

DB::commit();
return Response::json(true);

private function addActionees($actionees, $id, $status) {
    DB::table('task_assignee_user')->where('task_id', $id)->delete(); 
    foreach ($actionees as $act) {
        $actAdd = array(
            'task_id' => $id,
            'user_id' => $act->user_id,
        );
        DB::table('task_assignee')->insert($actAdd);
    }
}
  1. 开始交易。
  2. 执行CRUD操作。
  3. 捕获异常并回滚事务。
  4. 如果操作执行顺利,则提交交易。
  5. 修改:

    addActionees总是返回true,因为delete()方法在执行失败时不会抛出异常。因此$this->addActionees(Input::get('actionees'), $id)总是返回true。 让我们手动抛出异常:

    private function addActionees($actionees, $id, $status) {
        $deleteResult = DB::table('task_assignee_user')->where('task_id', $id)->delete(); 
        foreach ($actionees as $act) {
            $actAdd = array(
                'task_id' => $id,
                'user_id' => $act->user_id,
            );
            DB::table('task_assignee')->insert($actAdd);
        }
    
        if ($deleteResult  == 0) {
            throw new Exception('Delete failed');
        }
    }