利用Laravel事件系统优化下单功能多表关联插入处理[支持事务回滚]
迁移文件
订单表迁移文件
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 '订单表'");
订单报名学生信息表
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 '订单报名学生信息表'");
订单营期数据迁移文件
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 '订单营期数据'");
订单课程迁移文件
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 '订单课程'");
执行迁移文件
php artisan migrate
注册监听事件
注册监听事件
App\Providers\EventServiceProvider
# protected $listen = [ Registered::class => [ SendEmailVerificationNotification::class, ], //键为事件 //值为数组(监听器) 'App\Events\OrdersCreatedEvent'=>[ 'App\Listeners\OrdersStudentsListener', 'App\Listeners\OrdersCoursesCampsListener', 'App\Listeners\OrdersCoursesListener', ] ];
使用命令创建事件和监听器
php artisan event:generate
下单
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')
]);
}
}
本作品采用《CC 协议》,转载必须注明作者和本文链接