Votre MVP commence ici.
CoreEngine est un moteur PHP ultra-léger (600ko) conçu pour les développeurs qui veulent valider leurs idées rapidement sans sacrifier la structure et la sécurité.
Installation Rapide (Docker)
CoreEngine est livré avec une pile Docker complète pour un déploiement instantané. Plus besoin de configurer Apache ou MySQL localement.
1. Pré-requis
- Docker & Docker Compose
- Node.js & NPM
2. Lancement
# 1. Lancer l'infrastructure
docker-compose up --build -d
# 2. Installer & Compiler le Front
npm install
npm run dev
Et hop ! C'est prêt.
Rendez-vous sur localhost:8081.
Le fichier .env est déjà pré-configuré pour communiquer
avec les containers Docker (DB_HOST=db, etc.).
Configuration (.env)
CoreEngine utilise un chargeur d'environnement personnalisé pour isoler vos paramètres sensibles. Le
fichier .env est automatiquement parsé et typé pour faciliter son utilisation dans votre
code.
// Fichier .env
APP_DEBUG=true
APP_MAINTENANCE=false
DB_HOST=127.0.0.1
DB_NAME=core_db
DB_USER=root
// Utilisation du Helper
Utilisez la fonction globale env(). Elle gère automatiquement les valeurs par
défaut et le casting des types :
// Récupération avec valeur par défaut
$debug = env('APP_DEBUG', false);
// Le helper transforme les strings du .env :
// "true" => true (bool)
// "false" => false (bool)
// "null" => null (null)
À éviter
$db = $_ENV['DB_NAME'];
Recommandé (CoreEngine Way)
$db = env('DB_NAME', 'default_db');
Mode Maintenance intégré
Grâce à votre env_loader.php, passer APP_MAINTENANCE=true intercepte
toutes les requêtes pour rediriger vers la vue de maintenance avec un code 503.
Maintenance & Mode Recovery
Parce qu'un crash en production arrive toujours au mauvais moment, CoreEngine intègre un
Cockpit de survie autonome.
Même si le noyau est corrompu ou les variables .env erronées,
le mode Recovery vous permet de reprendre la main.
1. Accès Sécurisé
Accédez au fichier recovery.php à la racine de votre projet.
Utilisez votre EMERGENCY_TOKEN défini dans le script pour
déverrouiller la session.
https://votre-domaine.com/recovery.php
2. Capacités du Cockpit
- Check d'intégrité via Manifeste
- Hot-Swap de variables .env
- Test de liaison Database en temps réel
- Déploiement & Rollback de ZIP
Sécurité Critique
Le mode Recovery est conçu pour être 100% autonome.
Il ne dépend d'aucune classe du CoreEngine pour fonctionner, ce qui garantit son exécution
même si le framework est totalement hors service.
Conseil : Changez le token par défaut immédiatement
après l'installation.
Architecture Avancée
Le framework repose sur une arborescence stricte séparant le code métier de la mécanique interne, avec une gestion hybride de l'autoloading (Natif + Composer optionnel).
// Service Providers
Les Providers sont les points centraux où les services (Database, Auth) sont enregistrés dans le Container.
// config/app.php
'providers' => [
\App\Providers\DatabaseServiceProvider::class,
\App\Providers\AuthServiceProvider::class,
]
// Helpers Globaux
Des fonctions utilitaires disponibles partout sans import :
- csrf_field() : Génère un input de sécurité
- redirect($path) : Redirection HTTP immédiate
- env($key, $default) : Accès sécurisé à la config
// Structure des Dossiers
├── app/ # Code métier (Contrôleurs, Modèles, Middlewares)
├── config/ # Cœur du framework (Facades, Router) - NE PAS TOUCHER
├── database/ # Fichiers de Seeders et Migrations
├── public/ # Point d'entrée (index.php) et ressources (css, js)
├── resources/ # Vues de l'application (HTML/PHP pur)
├── routes/ # Fichiers de définition des routes (web.php)
├── vendor/ # Autoloader natif + paquets Composer éventuels
├── .env # Configuration d'environnement isolé
└── artisan # Assistant en ligne de commande
Mode Maintenance
Activez APP_MAINTENANCE=true dans votre .env pour rediriger instantanément
tous les utilisateurs vers la page /maintenance avec un code HTTP 503.
Autoloader & Composer (Optionnel)
CoreEngine est conçu pour fonctionner de manière 100% autonome, sans nécessiter Composer. Cependant, il est assez flexible pour s'intégrer avec si vous souhaitez utiliser des librairies externes de l'écosystème PHP.
Fonctionnement de l'Autoloader Hybride
Le point d'entrée public/index.php vérifie d'abord l'existence de l'autoloader de
Composer. S'il est trouvé, il est chargé. Ensuite, l'autoloader natif de CoreEngine est chargé,
assurant que le framework fonctionne dans tous les cas.
// public/index.php
// 1. Intégration de l'autoloader Composer (Optionnel)
if (file_exists(dirname(__DIR__) . '/vendor/autoload.php')) {
require_once dirname(__DIR__) . '/vendor/autoload.php';
}
// 2. Chargement de l'autoloader natif de CoreEngine
require_once dirname(__DIR__) . '/vendor/coreengine-autoload.php';
Liberté Totale
Cette approche vous donne le meilleur des deux mondes :
- Utilisez
composer require ma-librairie/super-outilpour vos projets complexes. - Déployez un projet CoreEngine par simple copie FTP/SSH sans jamais avoir à vous soucier de Composer pour les projets plus simples.
vendor de Composer est absent.
Cycle d'une requête
Chaque interaction avec CoreEngine suit un flux linéaire et sécurisé, transformant une
Request en Response à travers une pile de composants intelligents.
Capture & Sanitize
L'objet Request capture GET/POST/JSON et nettoie
récursivement les données contre les XSS.
Regex Matching
Le Router analyse l'URI, extrait les paramètres
dynamiques {id} et identifie la cible.
Middlewares
La requête traverse une pile de filtres. Chaque couche peut interrompre ou modifier le flux.
Auto-Injection
Le contrôleur est instancié via Reflection avec
injection automatique des dépendances du Container.
L'Objet Request
// Utilisation dans un contrôleur
public function store(Request $request) {
$email = $request->input('email');
$data = $request->only(['name', 'role']);
$id = $request->param('id'); // Param de route
}
L'objet Request supporte nativement le JSON (pour vos APIs) et le
form-data classique de manière totalement transparente.
L'Objet Response
// Helper statiques fluides
Response::json(['status' => 'success'], 201);
Response::redirect('/dashboard');
Response::notFound("Article introuvable");
La classe Response standardise les sorties et gère les entêtes HTTP ainsi que les
codes de statut automatiquement.
Résolution Intelligente (Reflection API)
Contrairement aux routeurs basiques, le Router de CoreEngine utilise l'API Reflection
de PHP pour inspecter le constructeur de vos contrôleurs.
Il injecte automatiquement les dépendances enregistrées dans le Container sans que vous
n'ayez à instancier quoi que ce soit manuellement.
Système de Routage
Le routeur de CoreEngine est un moteur de résolution dynamique. Il gère l'extraction de paramètres via Regex, l'injection automatique de dépendances et une pile de middlewares bidirectionnelle.
// Syntaxe & Vues
Liez une URL à une logique métier ou rendez une vue statique instantanément.
// Closure simple
Route::get('/api/status', fn() => ["status" => "ok"]);
// Rendu direct (resources/Views/welcome.php)
Route::view('/', 'welcome');
// Groupement de Contrôleur
Centralisez la logique d'un module pour un code plus propre.
Route::controller(UserController::class, function($router) {
$router->get('/profile', 'show');
$router->post('/profile', 'update');
});
Paramètres Dynamiques
Les segments entre {accolades} sont convertis en groupes de capture Regex
et injectés dans l'objet Request.
Injection de Dépendances (DI)
Grâce à ReflectionClass, votre contrôleur reçoit automatiquement ses
services via son constructeur.
public function __construct(Database $db, Mailer $mail) {
$this->db = $db;
}
Middleware Pipeline (Onion Architecture)
"Chaque middleware enveloppe le suivant. Le Router utilise array_reduce pour
créer cette structure en oignon."
AuthMiddleware
LogMiddleware
Controller
Route::get('/admin', [AdminController::class, 'index'], [
AuthMiddleware::class,
AdminMiddleware::class
]);
Middlewares
Les middlewares agissent comme des gardiens. Ils interceptent la Request avant qu'elle
n'atteigne le contrôleur, permettant de filtrer, valider ou rediriger le flux selon des règles métier
précises.
// 1. Structure d'un Middleware
namespace App\Middlewares;
use Config\Facades\Http\Request;
use Config\Facades\Http\Response;
class AuthMiddleware {
public function handle(Request $request, callable $next) {
if (!isset($_SESSION['user'])) {
return Response::redirect('/login');
}
return $next($request);
}
}
// 2. Mécanique du Pipeline
- Validation : Vérifie l'état de la session, les permissions ou la présence de jetons (JWT/CSRF).
-
Interruption : Si la condition échoue, le middleware utilise
Responsepour stopper le cycle. -
Propagation :
$next($request)passe la main à la couche suivante de l'oignon.
// 3. Enregistrement sur les Routes
L'application est simple : passez un tableau de classes (FQCN) en troisième argument de vos définitions de routes.
Route::get('/admin/dashboard', [AdminController::class, 'index'], [
\App\Middlewares\AuthMiddleware::class,
\App\Middlewares\RoleAdminMiddleware::class
]);
Optimisation du Pipeline
CoreEngine utilise array_reduce pour compiler la pile de middlewares en une seule
fonction anonyme (Closure) lors de la résolution de la route. Cette approche garantit une
exécution ultra-rapide, peu importe le nombre de couches.
Base de Données & Service Provider
La connexion n'est pas simplement globale : elle est injectée via le Container. Le
DatabaseServiceProvider centralise la configuration, rendant la base de données
disponible partout de manière découplée et hautement performante.
// DatabaseServiceProvider.php
$container->set(PDO::class, function () {
// Charge l'instance PDO depuis la config centrale
return require 'config/database.php';
});
// Initialise la Facade DB avec l'instance résolue
DB::boot($container->get(PDO::class));
Initialisation "Lazy Load"
Grâce à la fermeture (closure) dans le Container, la connexion PDO n'est établie que
lors du premier appel.
Si une requête (ex: page statique) n'utilise pas DB, aucune ressource serveur
n'est consommée.
Le rôle de DB::boot()
Cette méthode lie l'instance PDO unique à la Facade statique. Cela permet d'utiliser
DB::table() avec une syntaxe fluide tout en conservant une base saine et testable
en arrière-plan.
Environnements Hybrides
Le Provider utilise les variables d'environnement pour basculer dynamiquement entre l'hôte
Docker et
127.0.0.1, garantissant un workflow identique en local et en production.
Query Builder (DB Facade)
Avant l'ORM, il y a le Query Builder. C'est une interface fluide et sécurisée pour
construire des requêtes SQL complexes via la façade DB. Il est idéal pour les requêtes qui
ne nécessitent pas d'hydratation en Modèles.
// Sélectionner des utilisateurs actifs
$users = DB::table('users')
->select('id', 'email')
->where('status', '=', 'active')
->orderBy('created_at', 'DESC')
->get(); // Retourne une Collection de tableaux associatifs
// Compter les articles
$count = DB::table('articles')->count();
// Insertion
$id = DB::table('logs')->insert([
'level' => 'info',
'message' => 'User logged in'
]);
Artisan CLI
L'interface en ligne de commande de CoreEngine automatise la création de fichiers et la gestion de la base de données. Elle intègre une détection intelligente de l'environnement pour faciliter le passage entre Docker et votre système hôte.
// Génération de Boilerplate
# Créer un contrôleur
php artisan make:controller UserController
# Créer un modèle (Table auto au pluriel)
php artisan make:model UserModel
# Créer un modèle avec table spécifique
php artisan make:model PostModel blog_posts
// Base de données & Workflow
# Lancer le seeder par défaut (DatabaseSeeder)
php artisan db:seed
# Lancer un seeder spécifique
php artisan db:seed UserSeeder
Options Avancées
Pour les développements hors conteneur (ex: PowerShell), forcez la connexion locale :
--host=127.0.0.1
[CoreEngine] model créé avec succès : app/Models/PostModel.php (Table: blog_posts)
Contrôleurs
Les contrôleurs étendent la classe Config\Facades\Controllers\Controllers. Ils bénéficient
de l'injection automatique de PDO et de méthodes utilitaires pour le rendu, les API et la gestion de
fichiers.
// Structure Standard
namespace App\Controllers;
use Config\Facades\Controllers\Controllers;
use Config\Facades\Http\Request;
class UserController extends Controllers {
public function index(Request $request) {
return $this->render('users/profile', [
'user' => 'Jalal'
]);
}
}
// API & Téléchargements
CoreEngine facilite les réponses standardisées :
// Réponse JSON structurée
return $this->response("1", true, $data, "Succès", 200);
// Téléchargement sécurisé
return $this->makeDownload('facture.pdf');
Auto-PDO
L'instance PDO est injectée au constructeur et disponible via $this->pdo dans
toutes vos méthodes.
Smart Download
makeDownload() gère les headers HTTP, le nettoyage du tampon (OB) et la
vérification d'existence du fichier.
JSON Factory
La méthode response() garantit que vos API renvoient toujours un format constant :
{r, success, datas, message}.
Protection des vues
La méthode render de la classe Controllers inclut une protection
!defined('UNIT_TESTING'), permettant de tester vos contrôleurs sans déclencher
l'affichage des fichiers de vue.
Modèles & ORM
L'ORM de CoreEngine repose sur un QueryBuilder fluide et un système de Single Source of Truth. Le schéma de votre base de données est défini directement dans vos modèles, permettant l'auto-migration et une protection stricte des données.
1. Schéma & Source de Vérité
Définissez vos colonnes et leurs types SQL. Ce tableau sert à la fois de protection et de plan de construction pour la base de données.
class UserModel extends Models {
protected static string $tableName = 'users';
// Définition SQL + Protection de masse
protected static array $schemaColumns = [
"id" => "INT AUTO_INCREMENT PRIMARY KEY",
"email" => "VARCHAR(255) NOT NULL UNIQUE",
"firstName" => "VARCHAR(100)",
"password" => "VARCHAR(255) NOT NULL",
"role_id" => "INT DEFAULT 1"
];
}
2. Requêtes Fluides
Le modèle agit comme un pont vers le QueryBuilder. Les appels statiques sont automatiquement redirigés.
// Récupère une Collection d'objets UserModel
$users = UserModel::where('role_id', '=', 2)
->orderBy('firstName', 'DESC')
->limit(10)
->get();
// Hydratation automatique depuis un ID
$user = UserModel::find(1);
Auto-Migration
Générez vos tables SQL d'un simple appel à
UserModel::migrate().
Sécurité Native
Protection stricte via __set() :
impossible d'écrire dans une colonne non définie.
Active Record
save() détecte automatiquement s'il doit
effectuer un INSERT ou un UPDATE.
Hydratation
Les résultats de requêtes sont transformés instantanément en instances de Modèles.
Cycle de vie des données
$user = new UserModel();
$user->firstName = "Jalal"; // Vérifie si 'firstName' existe dans $schemaColumns
$user->save(); // INSERT - ID généré automatiquement
$user->email = "jalal@coreengine.dev";
$user->save(); // UPDATE - L'ID est présent, le moteur cible l'enregistrement
Collections
Les Collections sont des enveloppes puissantes pour les tableaux de données. Elles sont retournées
automatiquement par le QueryBuilder et offrent des méthodes de manipulation chaînables.
// Filtrage & Transformation
$users = UserModel::all();
// Extraire uniquement les emails
$emails = $users->pluck('email');
// Filtrer les admins et trier par nom
$admins = $users->filter(function($user) {
return $user->role === 'admin';
})->sortBy('firstName', 'asc');
// Analyse de données
// Calculer le total des factures
$total = $invoices->sum('amount');
// Grouper les utilisateurs par ville
$cities = $users->groupBy('city');
// Vérification rapide
if ($users->isEmpty()) {
// ...
}
Itérable
Utilisez vos collections directement dans un foreach
grâce à l'interface IteratorAggregate.
JSON Ready
Envoyez une collection directement en réponse API : elle sera
automatiquement sérialisée via json_encode.
Polyvalence
Supporte aussi bien les tableaux d'objets (Modèles) que les tableaux associatifs classiques.
Exemple concret : Statistiques de ventes
CoreEngine permet de traiter des données complexes en une seule ligne :
$revenue = $orders->filter(fn($o) => $o->status === 'paid')->unique('customer_id')->sum('total');
Validation & Sécurité
La sécurité des données est intégrée nativement. Le Validator permet de vérifier
l'intégrité des entrées utilisateur avant tout traitement, tandis que les Modèles protègent la base de
données via un filtrage par colonnes.
// 1. Définir les règles dans le Modèle
class User extends Models {
protected static array $rules = [
'email' => 'required|email',
'password' => 'required|min:8',
'age' => 'number',
'status' => 'boolean'
];
}
// 2. Valider une requête
public function store(Request $request) {
$validation = User::validate($request->all());
if (!$validation['success']) {
return view('register', [
'errors' => $validation['errors']
]);
}
// Données filtrées et validées
$user = (new User())->fill($validation['data']);
$user->save();
}
Règles disponibles
required : Champ obligatoire
email : Format email valide
text : Chaîne de caractères
number : Valeur numérique
boolean : `true`, `false`, `1`, `0`
min:x / max:x : Longueur min/max
date / timestamp : Format
temporel
Protection Mass-Assignment
Grâce à la propriété $schemaColumns de vos modèles, CoreEngine ignore automatiquement
toute donnée reçue qui ne correspond pas à une colonne réelle de votre table SQL. Cela empêche
l'injection de colonnes malveillantes lors d'un fill().
Authentification & Rôles
CoreEngine intègre un système d'authentification complet via la façade Auth et une gestion
des permissions via la façade Role.
// Façade Auth
Gérez le cycle de vie de la session utilisateur.
// Vérifier si l'utilisateur est connecté
if (Auth::check()) { ... }
// Récupérer l'ID de l'utilisateur connecté
$userId = Auth::id();
// Récupérer le modèle User complet
$user = Auth::user();
// Connecter un utilisateur (après vérification du mot de passe)
Auth::login($userModelInstance);
// Déconnecter l'utilisateur
Auth::logout();
// Façade Role
Vérifiez les permissions de l'utilisateur connecté.
// Vérifier si l'utilisateur a un rôle spécifique
if (Role::is('ADMIN')) {
// Logique réservée aux administrateurs
}
// Vérifier si l'utilisateur a l'un des rôles
if (Role::isOneOf(['ADMIN', 'MODERATOR'])) {
// ...
}
// Middleware de rôle
class RoleAdminMiddleware {
public function handle(Request $request, callable $next) {
if (!Role::is('ADMIN')) {
return Response::redirect('/unauthorized');
}
return $next($request);
}
}
Vues & Rendu
CoreEngine utilise un système de rendu basé sur PHP pur pour une performance maximale. Les vues sont isolées, ce qui signifie qu'elles n'ont accès qu'aux variables que vous leur passez explicitement.
// Structure des fichiers
- resources/
- Views/
- home.php
- dashboard.php
// Retourner une vue
Depuis un contrôleur ou directement dans une route :
// Dans le Router
Route::view('/', 'home');
// Dans un Contrôleur
return $this->render('user/profile', [
'name' => 'Jalal',
'role' => 'Admin'
]);
Fonctionnement interne
extract($datas) transforme les clés de votre tableau en variables
locales disponibles dans la vue.
ob_start() pour capturer le rendu PHP avant de l'envoyer au
navigateur, permettant des manipulations de dernière minute.
<?= $var ?>
pour un affichage rapide et lisible.
Exemple : Afficher les erreurs de validation
<ul class="alert-red">
<?php foreach($errors as $field => $msgs): ?>
<li><?= $msgs[0] ?></li>
<?php endforeach; ?>
</ul>
<?php endif; ?>
Mail & Logs
CoreEngine fournit une interface unifiée pour l'envoi d'e-mails et la journalisation. Basé sur le Design Pattern Factory, le module Mail vous permet de basculer instantanément entre différents fournisseurs.
Mail Facade
use Config\Facades\Mail\Mail;
// Configuration via .env (MAIL_DRIVER=sendgrid|resend|smtp)
Mail::to('client@exemple.com')
->cc('admin@exemple.com')
->subject('Votre Commande')
->html('<h1>Merci !</h1>')
->send();
Changez de fournisseur en modifiant simplement MAIL_DRIVER dans votre
.env. Le code métier reste 100% identique.
Log Facade
use Config\Facades\Log;
Log::info("Nouvel utilisateur inscrit");
Log::warning("Tentative de connexion échouée");
Log::exception("Erreur inattendue détectée");
Le système de log gère l'écriture structurée de l'historique de votre application, nativement lisible depuis l'Administration Suite.
Tuto 1 : CRUD Complet de Tâches
Apprenez à combiner Modèle, ORM, Validation et Contrôleur pour construire un système complet de gestion de tâches (Create, Read, Update, Delete).
1 Le Modèle (Task.php)
On définit le schéma et les règles. On ajoute une colonne user_id pour lier la
tâche à un utilisateur.
// app/Models/Task.php
class Task extends Models {
protected static string $tableName = 'tasks';
protected static array $schemaColumns = [
"id" => "INT AUTO_INCREMENT PRIMARY KEY",
'title' => 'VARCHAR(255) NOT NULL',
'user_id' => 'INT NOT NULL',
'is_done' => 'BOOLEAN DEFAULT FALSE'
];
protected static array $rules = [
'title' => 'required|min:3|max:50',
];
}
2 Le Contrôleur (TaskController.php)
On crée les méthodes pour chaque action du CRUD.
// app/Controllers/TaskController.php
class TaskController extends Controllers {
// Affiche la liste des tâches et le formulaire
public function index() {
$tasks = Task::where('user_id', Auth::id())->get();
return $this->render('tasks/index', ['tasks' => $tasks]);
}
// Enregistre une nouvelle tâche
public function store(Request $request) {
$validation = Task::validate($request->all());
if (!$validation['success']) {
// Gérer les erreurs...
return Response::redirect('/tasks');
}
$task = new Task();
$task->fill($validation['data']);
$task->user_id = Auth::id();
$task->save();
return Response::redirect('/tasks');
}
// Met à jour le statut d'une tâche
public function update(Request $request) {
$task = Task::find($request->param('id'));
// Vérifier que la tâche appartient à l'utilisateur connecté
if ($task && $task->user_id == Auth::id()) {
$task->is_done = !$task->is_done;
$task->save();
}
return Response::redirect('/tasks');
}
// Supprime une tâche
public function destroy(Request $request) {
$task = Task::find($request->param('id'));
if ($task && $task->user_id == Auth::id()) {
$task->delete();
}
return Response::redirect('/tasks');
}
}
3 Les Routes (web.php)
On relie les URLs aux méthodes du contrôleur, en protégeant le tout derrière un middleware d'authentification.
// routes/web.php
Route::middlewares([AuthMiddleware::class], function() {
Route::get('/tasks', [TaskController::class, 'index']);
Route::post('/tasks', [TaskController::class, 'store']);
Route::post('/tasks/{id}/update', [TaskController::class, 'update']);
Route::post('/tasks/{id}/delete', [TaskController::class, 'destroy']);
});
Résultat
Vous avez maintenant un système de gestion de tâches fonctionnel et sécurisé, où chaque utilisateur ne voit et ne gère que ses propres tâches.
Tuto 2 : Espace Membre Sécurisé
Apprenez à protéger des sections de votre site avec les Middlewares et à afficher des données spécifiques à l'utilisateur connecté.
1 Le Middleware d'Authentification
Ce gardien vérifie si un utilisateur est connecté. Sinon, il le redirige vers la page de connexion.
// app/Middlewares/AuthMiddleware.php
class AuthMiddleware implements Middleware {
public function handle(Request $request, callable $next) {
if (!Auth::check()) {
return Response::redirect('/signin');
}
return $next($request);
}
}
2 Grouper les Routes Protégées
Utilisez Route::middlewares() pour appliquer un ou plusieurs middlewares à tout un
groupe de routes.
// routes/web.php
Route::middlewares([AuthMiddleware::class], function() {
Route::get('/dashboard', [DashboardController::class, 'index']);
Route::get('/profile', [ProfileController::class, 'show']);
// ... toutes vos autres routes membres
});
3 Le Contrôleur du Dashboard
Le contrôleur récupère l'utilisateur connecté via la façade Auth et ses tâches.
// app/Controllers/DashboardController.php
class DashboardController extends Controllers {
public function index() {
$user = Auth::user(); // Récupère l'objet UserModel complet
$tasks = Task::where('user_id', $user->id)->get();
$taskCount = $tasks->count();
return $this->render('dashboard', [
'user' => $user,
'tasks' => $tasks,
'taskCount' => $taskCount
]);
}
}
4 La Vue (dashboard.php)
Affichez les informations de manière dynamique.
<h1>Bienvenue, <?= $user->firstName ?> !</h1>
<p>Vous avez <?= $taskCount ?> tâches en cours.</p>
<ul>
<?php foreach($tasks as $task): ?>
<li><?= $task->title ?></li>
<?php endforeach; ?>
</ul>
Tuto 3 : Construire une API REST
Créez une API stateless et sécurisée pour gérer vos tâches. Idéal pour une application front-end (React, Vue.js) ou une app mobile.
1 Le Middleware d'API
Ce middleware vérifiera la présence d'un token dans l'en-tête Authorization. Pour
cet exemple, on imagine que chaque utilisateur a un api_token dans la base de
données.
// app/Middlewares/ApiAuthMiddleware.php
class ApiAuthMiddleware implements Middleware { // Note: `Middleware` interface should be imported
public function handle(Request $request, callable $next) {
$authHeader = $request->header('Authorization');
$token = null;
if ($authHeader && str_starts_with($authHeader, 'Bearer ')) {
$token = substr($authHeader, 7);
}
if (!$token) {
return Response::json(['message' => 'Unauthorized'], 401);
}
// Cherche l'utilisateur par son token
$user = UserModel::where('api_token', '=', $token)->first();
if (empty($user)) {
return Response::json(['message' => 'Invalid token'], 401);
}
// Authentifie l'utilisateur pour cette requête
Auth::login($user);
return $next($request);
}
}
2 Le Contrôleur d'API
Ce contrôleur ne renvoie jamais de vue, uniquement du JSON via la méthode
response().
// app/Controllers/Api/TaskController.php
class TaskController extends Controllers {
public function index() {
$tasks = Task::where('user_id', Auth::id())->get();
return $this->response("1", true, $tasks, "Tasks retrieved");
}
public function store(Request $request) {
// ... validation ...
$task = new Task();
$task->fill($request->only(['title']));
$task->user_id = Auth::id();
$task->save();
return $this->response("1", true, $task, "Task created", 201);
}
// ... méthodes show, update, destroy ...
}
3 Les Routes d'API
On groupe les routes sous un préfixe /api et on les protège avec notre nouveau
middleware.
// routes/web.php
Route::prefix('api', function() {
Route::middlewares([ApiAuthMiddleware::class], function() {
Route::get('/tasks', [Api\TaskController::class, 'index']);
Route::post('/tasks', [Api\TaskController::class, 'store']);
Route::get('/tasks/{id}', [Api\TaskController::class, 'show']);
Route::put('/tasks/{id}', [Api\TaskController::class, 'update']);
Route::delete('/tasks/{id}', [Api\TaskController::class, 'destroy']);
});
});
4 Tester avec cURL
Utilisez un client HTTP comme cURL pour interagir avec votre nouvelle API.
# Récupérer les tâches
curl -X GET http://localhost:8081/api/tasks \
-H "Authorization: Bearer VOTRE_API_TOKEN"
# Créer une tâche
curl -X POST http://localhost:8081/api/tasks \
-H "Authorization: Bearer VOTRE_API_TOKEN" \
-H "Content-Type: application/json" \
-d '{"title": "Apprendre CoreEngine"}'
Tuto 4 : Formulaire de Contact
Mettez en pratique la validation et le module d'envoi d'e-mails en créant un formulaire de contact fonctionnel.
1 Le Contrôleur (ContactController.php)
Ce contrôleur gérera l'affichage du formulaire et le traitement des données envoyées.
// app/Controllers/ContactController.php
use Config\Facades\Validation\Validator;
use Config\Facades\Mail\Mail;
class ContactController extends Controllers {
public function index() {
return $this->render('contact/form');
}
public function send(Request $request) {
$validator = new Validator();
$rules = [
'name' => 'required|text',
'email' => 'required|email',
'message' => 'required|min:10'
];
if (!$validator->validate($request->all(), $rules)) {
// Rediriger avec les erreurs et les anciennes données
return $this->render('contact/form', [
'errors' => $validator->errors(),
'old' => $request->all()
]);
}
// Envoi de l'email à l'administrateur
Mail::to(env('ADMIN_EMAIL', 'admin@test.com'))
->replyTo($request->input('email'))
->subject('Nouveau message de ' . $request->input('name'))
->text($request->input('message'))
->send();
// Rediriger avec un message de succès
return $this->render('contact/form', ['success' => true]);
}
}
2 Les Routes (web.php)
Deux routes suffisent : une pour afficher le formulaire, une pour le traiter.
// routes/web.php
Route::get('/contact', [ContactController::class, 'index']);
Route::post('/contact', [ContactController::class, 'send']);
3 La Vue (resources/Views/contact/form.php)
La vue affiche le formulaire, les messages d'erreur et le message de succès.
<?php if(isset($success)): ?> <div class="alert-success">Message envoyé !</div> <?php else: ?> <?php if(isset($errors)): ?> <ul class="alert-danger"> <?php foreach($errors as $field => $error): ?> <li><?= htmlspecialchars($error[0]) ?></li> <?php endforeach; ?> </ul> <?php endif; ?> <form action="/contact" method="POST"> <?= csrf_field() ?> <input type="text" name="name" value="<?= htmlspecialchars($old['name'] ?? '') ?>"> <input type="email" name="email" value="<?= htmlspecialchars($old['email'] ?? '') ?>"> <textarea name="message"><?= htmlspecialchars($old['message'] ?? '') ?></textarea> <button type="submit">Envoyer</button> </form> <?php endif; ?>