您当前的位置: 首页 > 慢生活 > 程序人生 网站首页程序人生
编辑Task相关的数据验证及权限(laravel11队列关联用户task获取jobId)
发布时间:2024-11-07 22:07:34编辑:雪饮阅读()
-
其实要说这个编辑Task相关的数据验证及权限上篇已经实现了。
那么这次主要是为了实现邮件发送队列。
./vendor/bin/sail artisan make:job ProcessSendEmail
然后产生一个邮件发送类
./vendor/bin/sail artisan make:mail TaskMail
创建邮件模板
./vendor/bin/sail artisan make:view TaskEmail
编写邮件模板TaskEmail.blade.php
<div>
邮件内容: {{ $EmailContent }}
</div>
为邮件类接收邮件内容和邮件主题做准备
TaskMail.php中实现构造函数
public function __construct($subject,$content)
{
$this->EmailSubject=$subject;
$this->EmailContent=$content;
}
以及envelope的实现
public function envelope(): Envelope
{
return new Envelope(
subject: $this->EmailSubject,
);
}
和content的实现
public function content(): Content
{
return new Content('TaskEmail',with: ['EmailContent' => $this->EmailContent]);
}
配置发件服务器(以对接腾讯qq的个人邮箱为例)
在.env文件中配件发件服务器如
MAIL_MAILER=smtp
MAIL_HOST=smtp.qq.com
MAIL_PORT=25
MAIL_USERNAME=1509272975@qq.com
MAIL_PASSWORD=zxrnhbswatimhgfd
MAIL_ENCRYPTION=tls
MAIL_FROM_ADDRESS="1509272975@qq.com"
MAIL_FROM_NAME="${APP_NAME}"
这里25端口是腾讯qq的smtp个人邮箱发件端口
PASSWORD就是qq邮箱里面的那个授权码
qq邮箱现在好像必须https了,所以MAIL_ENCRYPTION配置理应为ssl,但我实际测试发现好像是tls才行。当然再此之前我有用过非25端口,也可能是这样导致的。
那么接下来我们就需要将之前task中指定的发送时间一起投递邮件发送任务到队列中,由于我还要实时测试,所以我就两个job一起投递了。
UserTask.php控制器的update实现则如
public function update(TaskUpdateRequest $request):RedirectResponse
{
$id=$request->input("id");
if($id){
$userTask=\App\Models\UserTask::find($id);
if (! Gate::allows('update-user-task', $userTask)) {
abort(403);
}
}
if(!$id){
$userTask=new \App\Models\UserTask();
}
$uid=$request->user()->id;
$type=$request->input("type");
$param=$request->input("param");
$userTask->uid=$uid;
$userTask->type=$type;
$userTask->param=json_encode($param);
$userTask->save();
ProcessSendEmail::dispatch($param);
ProcessSendEmail::dispatch($param)->delay(strtotime($param["sendTime"]));
return Redirect::route('user_task.add');
}
可以看到的是我们dispatch的时候进行传参的,所以邮件发送进程队列类ProcessSendEmail.php
的构造如
public function __construct($param)
{
$this->emailParam=$param;
}
然后实际的处理handle实现如
public function handle(): void
{
Mail::to($this->emailParam["email"])->send(new TaskMail($this->emailParam["subject"],$this->emailParam["body"]));
}
那么最后测试发送效果
那么接下来就顺带把userTask列表完成
UserTask控制的index实现
public function index(){
$tasks=\App\Models\UserTask::orderBy("id","desc")->get();
return Inertia::render('UserTask/Index',[
'tasks'=>$tasks
]);
}
这里可以看到我有关联按id查询一个task,是因为这里需要和编辑Task对接,就可以同用一个Add界面也作为task编辑的界面
UserTask模型别忘了关闭默认的时间戳处理
public $timestamps = false;
然后增加一个用户task列表的路由
Route::get('/user_task/index', [UserTask::class, 'index'])->name('user_task.index');
那么接下来实现task列表如
Y:\root\example-app\resources\js\Pages\UserTask\ Index.vue
<script setup>
import AuthenticatedLayout from '@/Layouts/AuthenticatedLayout.vue';
import {Head,Link } from '@inertiajs/vue3';
import { Edit} from '@element-plus/icons-vue'
const props=defineProps(['tasks']);
</script>
<template>
<Head title="Projects" />
<AuthenticatedLayout>
<div class="mt-6 bg-white shadow-sm rounded-lg divide-y">
<h1>task列表</h1>
<ul>
<template v-for="(task,index) in tasks">
<li>
<label>id:</label>
<span>{{task.id}}</span>
<div style="display: flex;justify-content: flex-end;">
<el-link :icon="Edit" :href="'/user_task/add?id='+task.id">Edit</el-link>
</div>
</li>
</template>
</ul>
</div>
</AuthenticatedLayout>
</template>
<style>
</style>
所以以前的新增task的Add.vue中也要获取下如果是从edit过来的情况
const props=defineProps(['task']);
以及form中也需要关联到id
const form = useForm({
id:0,
type:0,
param:{
email:"213532186@qq.com",
subject:"this is subject",
body:"this is body",
sendTime:dayjs().add(10, 'minute').format("YYYY-MM-DD HH:mm:ss")
},
});
有task属性的时候就初始化到form表单
//编辑时初始化表单
if(typeof(props.task)!="undefined"){
if(props.task.id){
form.id=props.task.id;
form.type=props.task.type;
form.param=props.task.param;
selectedOption.value=props.task.type;
}
}
提交的时候同样关联id
function submit() {
router.post(`/user_task/update`, {
_method: 'patch',
type: form.type,
param:form.param,
id:form.id
},{
onSuccess:()=>{
console.log("task提交完成");
formError.value={};
},
onError:(errors)=>{
console.log("task提交错误",errors);
formError.value=errors;
}
})
}
那么接下来我们还需要调整user_task关联job_id,因为原来的逻辑是没有的
alter table user_task add column `job_id` int NOT NULL;
然后根据编辑与新增以及由于dispatch时并不能直接获取到job的id,所以我们需要从jobs表中获取最后一条,并在编辑时候删除之前存储的job_id。那么此种逻辑,所以此处应该是需要原子性操作逻辑,但大多数情况下是无需的。只有并发时候才需要。我这里只是测试的本地项目,暂时先不处理,所以最终的UserTask控制器的update实现如:
public function update(TaskUpdateRequest $request):RedirectResponse
{
$id=$request->input("id");
if($id){
$userTask=\App\Models\UserTask::find($id);
if (! Gate::allows('update-user-task', $userTask)) {
abort(403);
}
}
if(!$id){
$userTask=new \App\Models\UserTask();
}
$uid=$request->user()->id;
$type=$request->input("type");
$param=$request->input("param");
$userTask->uid=$uid;
$userTask->type=$type;
$userTask->param=json_encode($param);
ProcessSendEmail::dispatch($param)->delay(strtotime($param["sendTime"]));
//删除原来的job
if($id){
if($userTask->job_id){
Jobs::find($userTask->job_id)->delete();
}
//兼容处理原来的数据没有job_id
$userTask->job_id=Jobs::orderBy("id","desc")->value("id");
}
if(!$id){
$userTask->job_id=Jobs::orderBy("id","desc")->value("id");
}
$userTask->save();
if($id){
return Redirect::route('user_task.add',["id"=>$id]);
}
return Redirect::route('user_task.add');
}
另外就是之前的UserTask新增编辑时候的权限问题,在AppServiceProvider.php中的boot方法中的实现
Gate::define('update-user-task', function (User $user, \App\Models\UserTask $userTask) {
return $user->id === $userTask->uid;
});
这里和之前相比是调整了UserTask类的调用为完全限定路径,之前就是直接UserTask忽略了一个问题就是用了同名的控制器。。。
本期词汇:
dispatch:派遣;发送
attempt:努力,尝试
attempts:尝试(attempt 的复数)
关键字词:laravel11,laravel,job,id,获取