Tuto Complet : CRUD avec Vue, Inertia & Laravel
Thème :
Intermédiaire
1 vues ·5/5 leçons

CRUD STUDENTS - LARAVEL 12 + INERTIA.JS + VUE 3 + TYPESCRIPT + WAYFINDER

Mise à jour Octobre 2025 - Configuration Professionnelle

-----------------------------------------------------------------------------

1. MIGRATION - database/migrations/2025_01_08_create_students_table.php

-----------------------------------------------------------------------------

id(); $table->string('name'); $table->string('email')->unique(); $table->enum('sexe', ['male', 'female', 'other']); $table->json('programs'); // ['php', 'js', 'html', 'typescript', 'vuejs', 'nuxtjs'] $table->string('profile')->nullable(); // Chemin image $table->string('country'); $table->enum('language', ['fr', 'en'])->default('fr'); $table->text('bio')->nullable(); $table->timestamps(); }); } public function down(): void { Schema::dropIfExists('students'); } }; # ----------------------------------------------------------------------------- # 2. MODEL - app/Models/Student.php # ----------------------------------------------------------------------------- 'array', ]; // Accessor pour l'URL complète du profil protected function profileUrl(): Attribute { return Attribute::make( get: fn () => $this->profile ? asset('storage/' . $this->profile) : null, ); } } # ----------------------------------------------------------------------------- # 3. FORM REQUEST - app/Http/Requests/StudentRequest.php # ----------------------------------------------------------------------------- route('student')?->id; return [ 'name' => ['required', 'string', 'max:255'], 'email' => ['required', 'email', 'max:255', Rule::unique('students')->ignore($studentId)], 'sexe' => ['required', Rule::in(['male', 'female', 'other'])], 'programs' => ['required', 'array', 'min:1'], 'programs.*' => [Rule::in(['php', 'js', 'html', 'typescript', 'vuejs', 'nuxtjs'])], 'profile' => ['nullable', 'image', 'max:2048', 'mimes:jpg,jpeg,png,webp'], 'country' => ['required', 'string', 'max:100'], 'language' => ['required', Rule::in(['fr', 'en'])], 'bio' => ['nullable', 'string', 'max:500'], ]; } public function messages(): array { return [ 'name.required' => 'Le nom est obligatoire.', 'email.required' => 'L\'email est obligatoire.', 'email.unique' => 'Cet email est déjà utilisé.', 'sexe.required' => 'Veuillez sélectionner un sexe.', 'programs.required' => 'Sélectionnez au moins un programme.', 'programs.min' => 'Sélectionnez au moins un programme.', 'profile.image' => 'Le fichier doit être une image.', 'profile.max' => 'La taille maximale est de 2 Mo.', 'country.required' => 'Le pays est obligatoire.', 'language.required' => 'La langue est obligatoire.', 'bio.max' => 'La bio ne peut pas dépasser 500 caractères.', ]; } } # ----------------------------------------------------------------------------- # 4. CONTROLLER - app/Http/Controllers/StudentController.php # ----------------------------------------------------------------------------- when($request->search, function ($query, $search) { $query->where('name', 'like', "%{$search}%") ->orWhere('email', 'like', "%{$search}%"); }) ->latest() ->paginate(10) ->withQueryString() ->through(fn ($student) => [ 'id' => $student->id, 'name' => $student->name, 'email' => $student->email, 'sexe' => $student->sexe, 'programs' => $student->programs, 'profile_url' => $student->profile_url, 'country' => $student->country, 'language' => $student->language, 'bio' => $student->bio, ]); return Inertia::render('Students/Index', [ 'students' => $students, 'filters' => $request->only('search'), ]); } // Formulaire de création public function create(): Response { return Inertia::render('Students/Create'); } // Enregistrer un nouvel étudiant public function store(StudentRequest $request) { $validated = $request->validated(); // Gérer l'upload de l'image if ($request->hasFile('profile')) { $validated['profile'] = $request->file('profile')->store('students/profiles', 'public'); } Student::create($validated); return redirect()->route('students.index') ->with('success', 'Étudiant créé avec succès.'); } // Afficher un étudiant public function show(Student $student): Response { return Inertia::render('Students/Show', [ 'student' => [ 'id' => $student->id, 'name' => $student->name, 'email' => $student->email, 'sexe' => $student->sexe, 'programs' => $student->programs, 'profile_url' => $student->profile_url, 'country' => $student->country, 'language' => $student->language, 'bio' => $student->bio, 'created_at' => $student->created_at->format('d/m/Y'), ], ]); } // Formulaire d'édition public function edit(Student $student): Response { return Inertia::render('Students/Edit', [ 'student' => [ 'id' => $student->id, 'name' => $student->name, 'email' => $student->email, 'sexe' => $student->sexe, 'programs' => $student->programs, 'profile_url' => $student->profile_url, 'country' => $student->country, 'language' => $student->language, 'bio' => $student->bio, ], ]); } // Mettre à jour un étudiant public function update(StudentRequest $request, Student $student) { $validated = $request->validated(); // Gérer le nouvel upload if ($request->hasFile('profile')) { // Supprimer l'ancienne image if ($student->profile) { Storage::disk('public')->delete($student->profile); } $validated['profile'] = $request->file('profile')->store('students/profiles', 'public'); } $student->update($validated); return redirect()->route('students.index') ->with('success', 'Étudiant mis à jour avec succès.'); } // Supprimer un étudiant public function destroy(Student $student) { // Supprimer l'image if ($student->profile) { Storage::disk('public')->delete($student->profile); } $student->delete(); return redirect()->route('students.index') ->with('success', 'Étudiant supprimé avec succès.'); } } # ----------------------------------------------------------------------------- # 5. ROUTES - routes/web.php # ----------------------------------------------------------------------------- group(function () { Route::resource('students', StudentController::class); }); # ----------------------------------------------------------------------------- # 6. TYPES TYPESCRIPT - resources/js/types/student.ts # ----------------------------------------------------------------------------- export type Sexe = 'male' | 'female' | 'other'; export type Language = 'fr' | 'en'; export type Program = 'php' | 'js' | 'html' | 'typescript' | 'vuejs' | 'nuxtjs'; export interface Student { id: number; name: string; email: string; sexe: Sexe; programs: Program[]; profile_url: string | null; country: string; language: Language; bio: string | null; created_at?: string; } export interface StudentFormData { name: string; email: string; sexe: Sexe | ''; programs: Program[]; profile: File | null; country: string; language: Language; bio: string; } export interface PaginatedStudents { data: Student[]; links: { first: string; last: string; prev: string | null; next: string | null; }; meta: { current_page: number; from: number; last_page: number; per_page: number; to: number; total: number; }; }

Prêt à passer à la suite ?

Vous avez terminé cette leçon sur CRUD STUDENTS - LARAVEL 12 + INERTIA.JS + VUE 3 + TYPESCRIPT + WAYFINDER. Continuez votre apprentissage avec la prochaine leçon ou explorez d'autres formations.