Laravel 有逻辑的事务
Laravel transactions with logic
我试图在我的交易中有逻辑,但它只是不断地将数据添加到数据库中,我不知道出了什么问题...
我目前拥有的代码:
public function addQuote($customer_id, Request $request)
{
//try catch, since there can be errors in it
DB::transaction(function() use ($customer_id, $request) {
try {
// Make a project for a quote, but not a main project, to not interfere with other existing projects
$quote_project = QuoteProject::create([
'projectnumber' => $request->project_number,
'name' => $request->project_name,
'address' => $request->project_address,
'zipcode' => $request->project_zipcode,
'city' => $request->project_city,
'country' => $request->project_country ?? 'BE',
'customer_id' => $customer_id,
]);
// Make a quote
$quote = Quote::create([
'status_id' => 1, // assign pending status
'reference' => $request->reference,
'number' => rand(),
'department_id' => $request->department,
'project_id' => $quote_project->id, // Created project id
'location_id' => ($request->location === 0) ? null : $request->location, // location -> can be 0 as value, if so, leave empty
'customer_id' => $customer_id,
'contact_id' => $request->contact_id,
'layout_id' => $request->layout_id,
'seller_id' => $request->seller_id,
'date_from' => Carbon::createFromFormat('d/m/Y', $request->date_from)->format('Y-m-d'),
'date_till' => Carbon::createFromFormat('d/m/Y', $request->date_till)->format('Y-m-d'),
'document_number' => $request->document_number,
'customer_number' => $request->customer_number,
'vat_type_id' => $request->vat_type_id,
'vat_tariff_id' => $request->vat_tariff_id,
]);
$quote->conditions()->attach($request->payment_conditions);
if (isset($request->head_group)) {
// set a global sync data variable
$sync_data = [];
// Loop over all the head groups
foreach ($request->head_group as $key => $head_group) {
// create or update head group
$created_head_group = ArticleGroup::updateOrCreate([
'quote_id' => $quote->id,
'name' => $head_group ?? ''
], [
'comment' => $request->head_group_comment[$key] ?? '',
'head_group' => 1,
'parent_group' => null,
'bold' => filter_var($request->bold_head[$key], FILTER_VALIDATE_BOOLEAN) ?? false,
'italic' => filter_var($request->italic_head[$key], FILTER_VALIDATE_BOOLEAN) ?? false,
'underline' => filter_var($request->underline_head[$key], FILTER_VALIDATE_BOOLEAN) ?? false,
'color' => str_replace('#', '', $request->color_head[$key]) ?? null
]);
// Loop over the sub groups in a main group
foreach ($request->sub_group[$key] as $s_key => $sub_group) {
// Create or update a subgroup
$created_sub_group = ArticleGroup::updateOrCreate([
'quote_id' => $quote->id,
'name' => $sub_group ?? ''
], [
'comment' => $request->sub_group_comment[$key][$s_key] ?? '',
'head_group' => 0,
'parent_group' => $created_head_group->id,
'bold' => filter_var($request->bold_sub[$key][$s_key], FILTER_VALIDATE_BOOLEAN) ?? false,
'italic' => filter_var($request->italic_sub[$key][$s_key], FILTER_VALIDATE_BOOLEAN) ?? false,
'underline' => filter_var($request->underline_sub[$key][$s_key], FILTER_VALIDATE_BOOLEAN) ?? false,
'color' => str_replace('#', '', $request->color_sub[$key][$s_key]) ?? null
]);
// Loop over the articles in the subgroup
foreach ($request->articles[$key][$s_key] as $a_key => $article_id) {
if (isset($request->articles[$key][$s_key])) {
$id = explode('-', $article_id);
$sync_data[$id[0]] = [
'name' => $request->custom_article_name[$key][$s_key][$a_key],
'quantity' => $request->quantity[$key][$s_key][$a_key],
'thickness' => $request->thickness[$key][$s_key][$a_key],
'price' => $request->article_price[$key][$s_key][$a_key],
'description' => $request->description[$key][$s_key][$a_key],
'group_id' => $created_sub_group->id
];
}
}
}
}
$quote->articles()->sync($sync_data); // sync the articles
}
// return data for ajax call, since the wizard works via an ajax call submit
return url('customers/' . $customer_id . '/quotations/');
} catch (\Exception $ex) {
return response()->json(['error' => $ex->getMessage()], 500);
}
}
);
}
如果有人可以向我解释我在这里做错了什么,那将是一个非常大的帮助!
这是它的工作原理。如果在 DB::transaction
内部抛出异常,则事务会自动回滚。但是在您的实现中不会抛出异常,因为您在事务中捕获它并尝试 return 错误响应(顺便说一下,因为您在 DB::transaction(function() use ($customer_id, $request) {
行中错过了 return ,所以什么都行不通) .
最简单的解决方法是不在DB::transaction
内部而是在DB::transaction
外部捕获异常 - 然后它会按照您的预期运行,事务将回滚。
在某些情况下,替代解决方案不使用 DB::transaction
而是使用手册:
DB::beginTransaction();
DB::rollBack();
DB::commit();
如documentation所述。
我试图在我的交易中有逻辑,但它只是不断地将数据添加到数据库中,我不知道出了什么问题...
我目前拥有的代码:
public function addQuote($customer_id, Request $request)
{
//try catch, since there can be errors in it
DB::transaction(function() use ($customer_id, $request) {
try {
// Make a project for a quote, but not a main project, to not interfere with other existing projects
$quote_project = QuoteProject::create([
'projectnumber' => $request->project_number,
'name' => $request->project_name,
'address' => $request->project_address,
'zipcode' => $request->project_zipcode,
'city' => $request->project_city,
'country' => $request->project_country ?? 'BE',
'customer_id' => $customer_id,
]);
// Make a quote
$quote = Quote::create([
'status_id' => 1, // assign pending status
'reference' => $request->reference,
'number' => rand(),
'department_id' => $request->department,
'project_id' => $quote_project->id, // Created project id
'location_id' => ($request->location === 0) ? null : $request->location, // location -> can be 0 as value, if so, leave empty
'customer_id' => $customer_id,
'contact_id' => $request->contact_id,
'layout_id' => $request->layout_id,
'seller_id' => $request->seller_id,
'date_from' => Carbon::createFromFormat('d/m/Y', $request->date_from)->format('Y-m-d'),
'date_till' => Carbon::createFromFormat('d/m/Y', $request->date_till)->format('Y-m-d'),
'document_number' => $request->document_number,
'customer_number' => $request->customer_number,
'vat_type_id' => $request->vat_type_id,
'vat_tariff_id' => $request->vat_tariff_id,
]);
$quote->conditions()->attach($request->payment_conditions);
if (isset($request->head_group)) {
// set a global sync data variable
$sync_data = [];
// Loop over all the head groups
foreach ($request->head_group as $key => $head_group) {
// create or update head group
$created_head_group = ArticleGroup::updateOrCreate([
'quote_id' => $quote->id,
'name' => $head_group ?? ''
], [
'comment' => $request->head_group_comment[$key] ?? '',
'head_group' => 1,
'parent_group' => null,
'bold' => filter_var($request->bold_head[$key], FILTER_VALIDATE_BOOLEAN) ?? false,
'italic' => filter_var($request->italic_head[$key], FILTER_VALIDATE_BOOLEAN) ?? false,
'underline' => filter_var($request->underline_head[$key], FILTER_VALIDATE_BOOLEAN) ?? false,
'color' => str_replace('#', '', $request->color_head[$key]) ?? null
]);
// Loop over the sub groups in a main group
foreach ($request->sub_group[$key] as $s_key => $sub_group) {
// Create or update a subgroup
$created_sub_group = ArticleGroup::updateOrCreate([
'quote_id' => $quote->id,
'name' => $sub_group ?? ''
], [
'comment' => $request->sub_group_comment[$key][$s_key] ?? '',
'head_group' => 0,
'parent_group' => $created_head_group->id,
'bold' => filter_var($request->bold_sub[$key][$s_key], FILTER_VALIDATE_BOOLEAN) ?? false,
'italic' => filter_var($request->italic_sub[$key][$s_key], FILTER_VALIDATE_BOOLEAN) ?? false,
'underline' => filter_var($request->underline_sub[$key][$s_key], FILTER_VALIDATE_BOOLEAN) ?? false,
'color' => str_replace('#', '', $request->color_sub[$key][$s_key]) ?? null
]);
// Loop over the articles in the subgroup
foreach ($request->articles[$key][$s_key] as $a_key => $article_id) {
if (isset($request->articles[$key][$s_key])) {
$id = explode('-', $article_id);
$sync_data[$id[0]] = [
'name' => $request->custom_article_name[$key][$s_key][$a_key],
'quantity' => $request->quantity[$key][$s_key][$a_key],
'thickness' => $request->thickness[$key][$s_key][$a_key],
'price' => $request->article_price[$key][$s_key][$a_key],
'description' => $request->description[$key][$s_key][$a_key],
'group_id' => $created_sub_group->id
];
}
}
}
}
$quote->articles()->sync($sync_data); // sync the articles
}
// return data for ajax call, since the wizard works via an ajax call submit
return url('customers/' . $customer_id . '/quotations/');
} catch (\Exception $ex) {
return response()->json(['error' => $ex->getMessage()], 500);
}
}
); }
如果有人可以向我解释我在这里做错了什么,那将是一个非常大的帮助!
这是它的工作原理。如果在 DB::transaction
内部抛出异常,则事务会自动回滚。但是在您的实现中不会抛出异常,因为您在事务中捕获它并尝试 return 错误响应(顺便说一下,因为您在 DB::transaction(function() use ($customer_id, $request) {
行中错过了 return ,所以什么都行不通) .
最简单的解决方法是不在DB::transaction
内部而是在DB::transaction
外部捕获异常 - 然后它会按照您的预期运行,事务将回滚。
在某些情况下,替代解决方案不使用 DB::transaction
而是使用手册:
DB::beginTransaction();
DB::rollBack();
DB::commit();
如documentation所述。