On créer une nouvelle page pour créer un projet et une nouvelle route:
Route::get('/project', [ProjectController::class, 'index']);
Route::get('/project/create', [ProjectController::class, 'create']);
Dans app/Http/Controller/ProjectController.php:
public function create()
{
return view('project.create');
}
Puis on créer resources/views/project/create.blade.php avec la même structure html
Optionnel: on peut ajouter un lien sous notre liste de projet
<a href="/project/create">Créer un nouveau projet</a>
@extends('layout')
@section('title','Project Create')
@section('content')
<h2>Créer un nouveau projet</h2>
<form>
<div>
<input type="text" name="title" placeholder="Titre du projet">
</div>
<div>
<textarea name="description" placeholder="Description du projet"></textarea>
</div>
<div>
<button type="submit">Créer le projet</button>
</div>
</form>
@endsection
→ on check et on test avec un submit
→ remarquer les paramètres get:
http://localhost:8000/projects/create?title=test+titre&description=test+description
On change le formulaire en post et on ajoute une action
<form method="POST" action="/project">
On a déjà une route ( route/web.php )
Route::get('/project', [ProjectController::class, 'index']);
→ Comment cela va donc marcher? On test -> HTTP exception
On créer une route en POST:
Route::post('/project', [ProjectController::class, 'store']);
//(store est une convention qu’il est conseillé de suivre)
Dans le controller ProjectController on ajoute la méthode store
public function store()
{
return request()->all(); //pour récupérer les informations du formulaire
}
Ajout d’un helper spécial @csrf dans le <form>
<form method="POST" action="/projects">
@csrf
On modifie la méthode store() dans le controller ProjectController pour sauvegarder en BDD
public function store()
{
$project = new Project(); //on instancie un nouveau projet
$project->title = request('title'); //on set le titre avec la donnée envoyée du formulaire
$project->description = request('description');
$project->save(); // on enregistre dans la base
return redirect('/project'); // méthode pour rediriger vers une autre url (en get par défaut)
}
Plutôt que d’instancier un model, assigner ses attributs et sauvegarder:
$project = new Project(); //on instancie un nouveau projet
$project->title = request('title'); //on set le titre avec la donnée envoyée du formulaire
$project->description = request('description');
$project->save(); // on enregistre dans la base
On peut assigner directement
Project::create(request(['title', 'description']));
Il faut le spécifier au model
protected $fillable = [
'title','description'
];
//protected $guarded = [];
request()->all() ou request('title') pour récupérer les données envoyées en post, puis on utilise la méthode Eloquent save() pour sauvegarder dans la base de données.REST (Representation State Transfert) est une façon de définir nos routes pour représenter nos fonctionnalités CRUD Dans un environnement REST, CRUD correspond souvent au méthodes http:
| Route / action | URL | Méthode HTTP | Description |
|---|---|---|---|
| Index | /projet | GET | Affiche la liste de tous les projets |
| Create | /projet/create | GET | Affiche un formulaire pour créer un nouveau projet |
| Store | /projet | POST | Ajoute un nouveau projet dans la base de donnée et redirige |
| Show | /projet/:id | GET | Affiche les information à propos d’un projet particulier |
| Edit | /projet/:id/edit | GET | Affiche un formulaire pour modifier un projet particulier |
| Update | /projet/:id | PUT | Met à jour un projet en particulier puis redirige |
| Destroy | /projet/:id | DELETE | Supprime un projet en particulier |
Artisan crée la structure typique d’un CRUD:
php artisan help make:controller
php artisan make:controller -r ProjectController
Dans la route:
Route::resource('/project', ProjectController::class);
On peut enregistrer plusieurs contrôleurs “ressource” à la fois:
Route::resources([
'photos' => ProjectController::class,
'posts' => PostController::class
])
Les formulaires HTML ne peuvent pas réaliser des requêtes PUT, PATCH ou DELETE (les formulaires peuvent uniquement faire des requêtes POST ou GET), on doit ajouter un champ caché @method. ex: @method('PUT')
Il est possible de limiter les actions acceptées par une route ressource:
Route::resource('photos', PhotoController::class)->only([
'index', 'show'
]);
Route::resource('photos', PhotoController::class)->except([
'create', 'store', 'update', 'destroy'
]);
On peut spécifier le modèle lié à un contrôleur ressource:
php artisan make:controller -r ProjectController -m "Project"
public function show($id)
{
$project = Project::find($id);
}
public function show(Project $project)
{
}
Le paramètre de la route doit correspondre
Route::get('/project/{project}', [ProjectController::class, 'show']);
On peut tout créer d'une seule commande:
php artisan make:model -a Project
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class Project extends Model
{
// Get the user the project.
public function user()
{
return $this->belongs(User::class);
}
// Get the tasks for the project.
public function tasks()
{
return $this->hasMany(Task::class);
// Select * from tasks where project_id = 1
}
}
<?php
$tasks = \App\Model\Project::find(1)->tasks;
foreach ($tasks as $task) {
//
}
public function up()
{
Schema::create('projects', function (Blueprint $table) {
$table->bigIncrements('id');
$table->unsignedBigInteger('user_id');
$table->string('title');
$table->text('description');
$table->timestamps();
$table->foreign('user_id')
->references('id')
->on('users')
->onDelete('cascade');
});
}
Ou on peut simplifier avec
public function up()
{
Schema::create('projects', function (Blueprint $table) {
$table->bigIncrements('id');
$table->string('title');
$table->text('description');
$table->timestamps();
$table->foreignId('user_id')
->constrained()
->onUpdate('cascade')
->onDelete('cascade');
});
}
php artisan make:factory ProjectFactory
public function definition()
{
return [
'user_id' => \App\Models\User::factory(),
'title' => $this->faker->sentence,
'description' => $this->faker->paragraph
];
}
\App\Models\Project::factory(5)->create();
Dans database/seeders/DatabaseSeeder.php on peut appeler nos factories:
public function run()
{
\App\Models\User::factory(2)->create();
\App\Models\Project::factory(10)->create();
}
Puis
php artisan migrate:fresh --seed -v
On peut lier nos factories et créer par exemple 5 projets par utilisateur:
public function run()
{
$users = \App\Models\User::factory(2)->has(\App\Models\Project::factory()->count(5))->create();
}
Nous devons d’abords lier notre modèle User avec notre modèle Project, dans notre model user on ajoute la méthode:
public function project()
{
return $this->hasMany(Project::class,'user_id');
}
Laravel offre une façon simple et efficace de valider les données soumises à l'aide de la méthode validate() disponible dans l'objet Request.
$request->validate([
'nom' => 'required|max:255',
'email' => 'required|email|unique:users,email_address',
]);
$errors qui contient un tableau avec comme clés les noms des contrôles et comme valeurs les textes identifiant les erreurs.$errors est générée systématiquement pour toutes les vues.On teste la présence d’une erreur pour chaque contrôle en ajustant le style et en affichant le texte de l’erreur si nécessaire avec la méthode first :
<p style="color:red">{{$errors->first('title')}}</p>
@if ($errors->has('title'))
<p style="color:red">{{$errors->first('title')}}</p>
@endif
Ou
@error('title')
<p style="color:red">{{$errors->first('title')}}</p>
@enderror
On peut aussi
<input @error('title') style="border-color:red" @enderror
Enfin en cas d’erreur de validation, les anciennes valeurs saisies sont retournées au formulaire et récupérées avec le helper old :
value="{{ old('nom') }}"
@if ($errors->any())
<div class="alert alert-danger">
<ul>
@foreach ($errors->all() as $error)
<li>{{ $error }}</li>
@endforeach
</ul>
</div>
@endif
app/Http/Middleware
Voir app/Http/Kernel pour le chargement.
Exemple avec laravel breeze:
https://laravel.com/docs/master/starter-kits#laravel-breeze
Attention cela va écraser certain fichier comme web.php ou des assets
composer require laravel/breeze --dev
php artisan breeze:install
npm install
npm run dev
php artisan migrate
php artisan route:list
Pour «protéger» une route, on utilise le middleware auth
Route::get('/dashboard', function () {
return view('dashboard');
})->middleware(['auth', 'verified'])->name('dashboard');
Ou un groupe de route
Route::middleware('auth')->group(function () {
Route::get('/profile', [ProfileController::class, 'edit'])->name('profile.edit');
Route::patch('/profile', [ProfileController::class, 'update'])->name('profile.update');
Route::delete('/profile', [ProfileController::class, 'destroy'])->name('profile.destroy');
});
Autre example
Route::get('/', [PagesController::class, 'home'])->middleware('auth');
→ On peut tester authentifié ou non
Dans la vue:
@auth
Bonjour {{ Auth::user()->name }}!
@else
Bonjour vous n'êtes pas authentifié <a href="{{ route('login') }}">Log in</a>
@endauth
ou l'inverse
@guest
@endguest
install
npm install
charger les styles et scripts
<! doctype html>
<head>
{{-- ... --}}
@vite(['resources/css/app.css', 'resources/js/app.js'])
</head>
.env → driver log MAIL_MAILER=log tail -f)Envoi d’un mail:
Mail::raw('Ça marche', function ($message) {
$message->to('email@test.com')
->subject('Salut');
});
On modifie la méthode store() de notre ProjectController
Project::create(array_merge(request(['title', 'description']), ['user_id' => auth()->id()]));
→ Ne pas oublié d'ajouter user_id dans les fillables de project
Ou mieux on surcharge la méthode save() du model Project
public function save(array $options = array())
{
$this->user_id = auth()->id();
parent::save($options);
}
On modifie la méthode store() de notre ProjectController
Mail::raw('Projet '.request('title').': '.request('description'), function ($message) {
$message->to('admin@monsite.com')
->subject('Projet créé: '. request('title') );
});
Ajouter en haut du controller
use Illuminate\Support\Facades\Mail;
Dans la méthode store() du controller Project
return redirect('/project')
->with('message', 'Projet créé!');
Puis dans la vue
@if (session('message'))
<div>
{{ session('message')}}
</div>
@endif
shéma
Creation Event
php artisan event:list
php artisan make:event ProjectCreated
On déclanche l'event dans le controller app\Http\Controller\ProjectController.php
ProjectCreated::dispatch($project);
→ « Un projet a été crée si quelqu'un à besoin de le savoir»
Création Listener
php artisan make:listener SuiviManager -e ProjectCreated
App\Listeners\SuiviManager.php
public function handle(ProjectCreated $event)
{
//
var_dump($event);
die('Die SuiviManager listener');
}
→ on test rien ne se passe -> on a pas lié les deux
Dans app\Providers\EventServiceProvider.php
use App\Events\ProjectCreated;
use App\Listeners\SuiviManager;
…
protected $listen = [
Registered::class => [
SendEmailVerificationNotification::class,
],
ProjectCreated::class => [
SuiviManager::class
]
];
→ La liaison dans le provider c'est bien c'est explicite mais difficile à maintenir on peut supprimer
Event discovery app\Providers\EventServiceProvider.php
public function shouldDiscoverEvents()
{
return true;
}
-> va scanner le répértoire listener
On peut envoyer un mail dans l'event
use Illuminate\Support\Facades\Mail;
…
public function handle(ProjectCreated $event): void
{
//
Mail::raw('Projet '.$event->project->title.': '.$event->project->description,
function ($message) use ($event){
$message->to('admin@monsite.com')
->subject('Projet créé: '. $event->project->title);
});
//die('Die SuiviManager listener');
}