利用Laravel事件系统优化下单功能多表关联插入处理[支持事务回滚]

迁移文件

  1. 订单表迁移文件

       Schema::create('orders', function (Blueprint $table) {
             $table->id();
             $table->foreignId('users_id')->index('users_id')->default(0)->comment('会员id');
             $table->string('orders_num')->index('orders_num')->default('')->comment('订单号');
             $table->string('a_categories_name')->nullable()->comment('一级分类');
             $table->string('b_categories_name')->nullable()->comment('二级分类');
             $table->string('courses_name')->nullable()->comment('课堂名称');
             $table->string('courses_image')->nullable()->comment('课堂图片');
             $table->decimal('total')->default(0)->comment('订单总价');
             $table->decimal('pay_total')->default(0)->comment('实付金额');
             $table->decimal('discount_total')->default(0)->comment('优惠金额');
             $table->tinyInteger('pay_status')->default(0)->comment('订金支付状态默认0未支付1已支付2支付失败');
             $table->tinyInteger('status')->default(0)->comment('订单状态默认0未成交1已成交2修改报名营期审核中');
             $table->timestamp('audit_time')->nullable()->comment('修改营期审核时间');
             $table->string('pay_type',50)->nullable()->comment('支付类型');
             $table->timestamp('pay_time')->nullable()->comment('支付时间');
             $table->timestamps();
         });
         \DB::statement("ALTER TABLE `xly_orders` comment '订单表'");
  2. 订单报名学生信息表

    Schema::create('orders_students', function (Blueprint $table) {
             $table->id();
             $table->foreignId('orders_id')->index('orders_id')->default(0)->comment('订单id');
             $table->string('student_name')->index('student_name')->default('')->comment('学员姓名');
             $table->integer('student_age')->default(0)->comment('学员年龄');
             $table->tinyInteger('student_gender')->default(0)->comment('性别0保密1男2女');
             $table->string('student_id_num')->index('student_id_num')->default(0)->comment('学员身份证号码');
             $table->string('parent_name')->index('parent_name')->default('')->comment('家长姓名');
             $table->string('parent_phone')->index('parent_phone')->default('')->comment('家长联系方式');
             $table->tinyInteger('is_medical_history')->default(0)->comment('有无病史0否1是');
             $table->tinyInteger('is_camp')->default(0)->comment('有无夏令营冬令营的经历0否1是');
             $table->string('remark')->nullable()->comment('其他补充(非必选)');
             $table->timestamps();
         });
         \DB::statement("ALTER TABLE `xly_orders_students` comment '订单报名学生信息表'");
  3. 订单营期数据迁移文件

      Schema::create('orders_courses_camps', function (Blueprint $table) {
             $table->id();
             $table->foreignId('orders_id')->index('orders_id')->default(0)->comment('订单id');
             $table->foreignId('courses_id')->index('courses_id')->default(0)->comment('课堂id');
             $table->string('title')->default('title')->comment('标题');
             $table->timestamp('start_time')->nullable()->comment('开始时间');
             $table->timestamp('end_time')->nullable()->comment('结束时间');
             $table->tinyInteger('is_void')->default(0)->comment('是否作废默认0否1是,用于修改营期判断');
             $table->timestamp('join_end_time')->nullable()->comment('截止报名时间');
             $table->timestamp('unable_join_at')->nullable()->comment('无法取消报名时间');
             $table->timestamps();
         });
         \DB::statement("ALTER TABLE `xly_orders_courses_camps` comment '订单营期数据'");
  4. 订单课程迁移文件

    Schema::create('orders_courses', function (Blueprint $table) {
             $table->id();
             $table->foreignId('orders_id')->index('orders_id')->default(0)->comment('订单id');
             $table->foreignId('a_categories_id')->index()->default(0)->comment('一级分类');
             $table->foreignId('b_categories_id')->index()->default(0)->comment('二级分类');
             $table->string('name')->index('name')->default('')->comment('课堂名称');
             $table->decimal('price')->default(0)->comment('价格');
             $table->decimal('share_total')->default(0)->comment('提成金额');
             $table->string('camp')->nullable()->comment('营地');
             $table->string('image')->nullable()->comment('图片');
             $table->json('images')->nullable()->comment('详情轮播图');
             $table->longText('graphic_details')->nullable()->comment('图文详情');
             $table->longText('schedule')->nullable()->comment('日程安排');
             $table->longText('dangerous_details')->nullable()->comment('注意事件');
             $table->timestamps();
         });
         \DB::statement("ALTER TABLE `xly_orders_courses` comment '订单课程'");
  5. 执行迁移文件

    php artisan migrate

注册监听事件

  1. 注册监听事件App\Providers\EventServiceProvider

     #
     protected $listen = [
      Registered::class => [
      SendEmailVerificationNotification::class,
       ],
       //键为事件
       //值为数组(监听器)
       'App\Events\OrdersCreatedEvent'=>[
           'App\Listeners\OrdersStudentsListener',
           'App\Listeners\OrdersCoursesCampsListener',
           'App\Listeners\OrdersCoursesListener',
       ]
     ];
  2. 使用命令创建事件和监听器

    php artisan event:generate

    利用Laravel事件系统优化表关联插入处理
    利用Laravel事件系统优化表关联插入处理

下单

   public function store(Request $request): HttpResponseException
    {
        $courses_model = Courses::query()->findOrFail($request->input('courses_id'));
        $courses_camp_model = CoursesCamp::query()->findOrFail($request->input('courses_camps_id'));
        DB::beginTransaction();
        try {
            $model = Orders::query()->create([
                'users_id' => Auth::id(),
                'orders_num' => Common::createOrdersNum('','orders_num'),
                'a_categories_name' => $courses_model->a_categories->name,
                'b_categories_name' => $courses_model->b_categories->name,
                'courses_name' => $courses_model->name,
                'courses_image' => $courses_model->image,
                'total' => $courses_model->price,
                'pay_total' => $courses_model->price,
                'discount_total' => 0,
            ]);
            event(new OrdersCreatedEvent($model, $request));//分发事件到监听器
            DB::commit();
        } catch (\Exception $exception) {
            DB::rollback();
            Logs::info('下单失败', $request->all(),'orders');
            Log::error($exception->getMessage());
            $errorRequest = new ErrorRequest();
            $errorRequest->setMessage($exception->getMessage());
            return Response::error($errorRequest);
        }
    }
<?php

namespace App\Events;

use App\Models\Orders;
use Illuminate\Broadcasting\Channel;
use Illuminate\Broadcasting\InteractsWithSockets;
use Illuminate\Broadcasting\PresenceChannel;
use Illuminate\Broadcasting\PrivateChannel;
use Illuminate\Contracts\Broadcasting\ShouldBroadcast;
use Illuminate\Foundation\Events\Dispatchable;
use Illuminate\Http\Request;
use Illuminate\Queue\SerializesModels;

class OrdersCreatedEvent
{
    use Dispatchable, InteractsWithSockets, SerializesModels;

    public Orders $model;
    public Request $request;

    public function __construct(Orders $orders,Request $request)
    {
        $this->model = $orders;
        $this->request = $request;
    }

    /**
     * Get the channels the event should broadcast on.
     *
     * @return \Illuminate\Broadcasting\Channel|array
     */
    public function broadcastOn()
    {
        return new PrivateChannel('channel-name');
    }
}
<?php

namespace App\Listeners;

use App\Events\OrdersCreatedEvent;
use App\Facades\Common;
use App\Facades\Response;
use App\Models\Courses;
use App\Models\CoursesCamp;
use App\Models\Orders;
use App\Models\OrdersCourses;
use App\Services\Response\Models\ErrorRequest;
use App\Services\Response\Models\SuccessRequest;
use App\Utils\Logs;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Log;

class OrdersCoursesCampsListener
{
    public function __construct()
    {
    }

    public function handle(OrdersCreatedEvent $event)
    {
        $courses_camp_model = CoursesCamp::query()->findOrFail($event->request->input('courses_camps_id'));
        $event->model->orders_courses_camps()->create([
            'courses_id' => $courses_camp_model->id,
            'title' => $courses_camp_model->title,
            'start_time' => $courses_camp_model->start_time,
            'end_time' => $courses_camp_model->end_time,
            'join_end_time' => $courses_camp_model->join_end_time,
            'unable_join_at' => $courses_camp_model->unable_join_at,
        ]);
    }
}
<?php

namespace App\Listeners;

use App\Events\OrdersCreatedEvent;
use App\Models\Courses;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Queue\InteractsWithQueue;

class OrdersCoursesListener
{
    public function __construct()
    {
    }

    public function handle(OrdersCreatedEvent $event)
    {
        $courses_model = Courses::query()->findOrFail($event->request->input('courses_id'));
        $event->model->orders_courses()->create([
            'a_categories_id' => $courses_model->a_categories_id,
            'b_categories_id' => $courses_model->b_categories_id,
            'name' => $courses_model->name,
            'price' => $courses_model->price,
            'share_total' => $courses_model->share_total,
            'camp' => $courses_model->camp,
            'image' => $courses_model->image,
            'images' => json_encode($courses_model->images),
            'graphic_details' => $courses_model->graphic_details,
            'schedule' => $courses_model->schedule,
            'dangerous_details' => $courses_model->dangerous_details,
        ]);
    }
}
<?php

namespace App\Listeners;

use App\Events\OrdersCreatedEvent;
use App\Models\Courses;
use App\Models\OrdersStudents;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Queue\InteractsWithQueue;

class OrdersStudentsListener
{
    public function __construct()
    {
    }

    public function handle(OrdersCreatedEvent $event)
    {
        $event->model->orders_students()->create([
            'student_name' => $event->request->input('student_name'),
            'student_age' => $event->request->input('student_age'),
            'student_gender' => $event->request->input('student_gender'),
            'student_id_num' => $event->request->input('student_id_num'),
            'parent_name' => $event->request->input('parent_name'),
            'parent_phone' => $event->request->input('parent_phone'),
            'is_medical_history' => $event->request->input('is_medical_history'),
            'is_camp' => $event->request->input('is_camp'),
            'remark' => $event->request->input('remark')
        ]);
    }
}

参考
官方文档
Laravel学习记录–Laravel事件系统

本作品采用《CC 协议》,转载必须注明作者和本文链接
《L04 微信小程序从零到发布》
从小程序个人账户申请开始,带你一步步进行开发一个微信小程序,直到提交微信控制台上线发布。
《L02 从零构建论坛系统》
以构建论坛项目 LaraBBS 为线索,展开对 Laravel 框架的全面学习。应用程序架构思路贴近 Laravel 框架的设计哲学。
讨论数量: 0
(= ̄ω ̄=)··· 暂无内容!

讨论应以学习和精进为目的。请勿发布不友善或者负能量的内容,与人为善,比聪明更重要!