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所述。