您当前的位置: 首页 > 慢生活 > 程序人生 网站首页程序人生
Task标记完成的逻辑、新建Task相关的数据验证及权限(laravel11+inertia手动实现表单验证)
发布时间:2024-11-06 21:48:39编辑:雪饮阅读()
-
其实Task标记完成的逻辑就在上篇中的Y:\root\example-app\app\Providers\AppServiceProvider.php
boot方法中已有实现新增逻辑
Queue::after(function (JobProcessed $event) {
info('after事件:'.$event->job->uuid());
$FinishJobs=new FinishJobs();
$FinishJobs->uuid=$event->job->uuid();
$FinishJobs->save();
});
接下来我想设计的是用户可以建立task,建立数据表如
CREATE TABLE `user_task` (
`id` int NOT NULL AUTO_INCREMENT,
`uid` int NOT NULL,
`type` int NOT NULL,
`param` text NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci
我是假定用户可以建立多种类型的task,然后这里用type来区分,用param来存储不同type的参数
然后创建模型
./vendor/bin/sail artisan make:model UserTask
关联表名
protected $table = 'user_task';
以及对应的控制器
./vendor/bin/sail artisan make:controller UserTask
并完成控制器的新增inertia视图
public function add(){
return Inertia::render('UserTask/Add
);
}
并先让新增Task的界面先出来
Y:\root\example-app\resources\js\Pages\UserTask\Add.vue
<script setup>
import AuthenticatedLayout from '@/Layouts/AuthenticatedLayout.vue';
import { Head } from '@inertiajs/vue3';
defineProps({
mustVerifyEmail: {
type: Boolean,
},
status: {
type: String,
},
});
</script>
<template>
<Head title="Project-Create" />
<AuthenticatedLayout>
<template #header>
<h2
class="text-xl font-semibold leading-tight text-gray-800 dark:text-gray-200"
>
Project-Create
</h2>
</template>
<div class="py-12">
<div class="mx-auto max-w-7xl space-y-6 sm:px-6 lg:px-8">
</div>
</div>
</AuthenticatedLayout>
</template>
以及路由
Route::get('/user_task/add', [UserTask::class, 'add'])->name('project.add');
实际上我的验证需求就是当type为1的时候即email则email的subject和body都要有且type必须选择1或2,且email必须符合邮箱格式。
那么要应对这些,首先前端这个页面的实现如:
<script setup>
import AuthenticatedLayout from '@/Layouts/AuthenticatedLayout.vue';
import InputError from '@/Components/InputError.vue';
import InputLabel from '@/Components/InputLabel.vue';
import PrimaryButton from '@/Components/PrimaryButton.vue';
import TextInput from '@/Components/TextInput.vue';
import {Head, router, useForm, usePage} from '@inertiajs/vue3';
import { ref, watch } from 'vue';
defineProps({
mustVerifyEmail: {
type: Boolean,
},
status: {
type: String,
},
});
const user = usePage().props.auth.user;
const selectedOption = ref(0);
var types = ref([
{
name:'Email',
picked:false,
val:1
}
]);
const form = useForm({
type:0,
param:{
email:"",
subject:"",
body:""
},
});
const formError=ref({});
watch(selectedOption, (newValue, oldValue) => {
console.log("selectedOption oldValue:",oldValue);
console.log("selectedOption newValue:",newValue);
form.type=parseInt(newValue);
});
function submit() {
router.post(`/user_task/update`, {
_method: 'patch',
type: form.type,
param:form.param
},{
onSuccess:()=>{
console.log("task提交完成");
formError.value={};
},
onError:(errors)=>{
console.log("task提交错误",errors);
formError.value=errors;
}
})
}
</script>
<template>
<Head title="Project-Create" />
<AuthenticatedLayout>
<template #header>
<h2
class="text-xl font-semibold leading-tight text-gray-800 dark:text-gray-200"
>
Task-Create
</h2>
</template>
<div class="py-12">
<div class="mx-auto max-w-7xl space-y-6 sm:px-6 lg:px-8">
<form
@submit.prevent="submit"
class="mt-6 space-y-6" enctype="multipart/form-data"
>
<div style="display: flex;align-items: center;gap:1rem;">
<InputLabel for="type" value="Type" />
<template v-for="(item,index) in types">
<input type="radio" name="type" :value="item.val" v-model="selectedOption" /> {{item.name}}
</template>
</div>
<template v-if="selectedOption == 1">
<div>
<InputLabel for="email" value="Receive Email Address" />
<TextInput
id="email"
type="text"
class="mt-1 block w-full"
v-model="form.param.email"
required
autofocus
autocomplete="email"
/>
<InputError class="mt-2" :message="formError['param.email']" />
<InputLabel for="subject" value="Subject" />
<TextInput
id="email"
type="text"
class="mt-1 block w-full"
v-model="form.param.subject"
required
autofocus
autocomplete="subject"
/>
<InputError class="mt-2" :message="formError['param.subject']" />
<InputLabel for="body" value="Body" />
<textarea
id="body"
class="mt-1 block w-full"
v-model="form.param.body"
required
autofocus
autocomplete="body"
/>
<InputError class="mt-2" :message="formError['param.body']" />
</div>
</template>
<div class="flex items-center gap-4">
<PrimaryButton :disabled="form.processing">Save</PrimaryButton>
<Transition
enter-active-class="transition ease-in-out"
enter-from-class="opacity-0"
leave-active-class="transition ease-in-out"
leave-to-class="opacity-0"
>
<p
v-if="form.recentlySuccessful"
class="text-sm text-gray-600 dark:text-gray-400"
>
Saved.
</p>
</Transition>
</div>
</form>
</div>
</div>
</AuthenticatedLayout>
</template>
最大的改变只是表单验证失败时对应的输入元素的提示用字符串作为错误key。
然后别忘记了提交的路由
Route::patch('/user_task/update', [UserTask::class, 'update'])->name('user_task.update');
于auth组里面。
那么为了实现上面的逻辑,仅仅是前端符合了inertia的规则,后端inertia响应于验证请求时同样需要处理。
所以Y:\root\example-app\app\Http\Requests\TaskUpdateRequest.php实现如:
<?php
namespace App\Http\Requests;
use App\Models\Project;
use App\Models\User;
use Illuminate\Foundation\Http\FormRequest;
use Illuminate\Validation\Rule;
class TaskUpdateRequest extends FormRequest
{
/**
* Get the validation rules that apply to the request.
*
* @return array<string, \Illuminate\Contracts\Validation\Rule|array|string>
*/
public function rules(): array
{
return [
'type' => [
'required',Rule::in([1,2])
],
'param.email'=>'required_if:type,1|email',
'param.subject'=>'required_if:type,1',
'param.body'=>'required_if:type,1'
];
}
}
那么上面这些仅仅只是满足了验证,还有就是权限方面也需要处理,所以在app的服务提供者里面还需要启动一个新的权限验证对于用户的task的建立的时候
Gate::define('update-user-task', function (User $user, UserTask $userTask) {
return $user->id === $userTask->uid;
});
那么最后UserTask控制器的update实现方法如:
public function update(TaskUpdateRequest $request):RedirectResponse
{
$id=$request->input("id");
if($id){
$userTask=UserTask::find($id);
if (! Gate::allows('update-user-task', $userTask)) {
abort(403);
}
}
return Redirect::route('user_task.add');
}
最后的实现效果如:
关键字词:laravel,inertia