Mini framework PHP MVC avec système de routing avancé, extrait de TekNotes.
- Caractéristiques
- Installation
- Configuration
- Utilisation
- Sécurité
- Documentation
- Roadmap
- Contribution
- Licence
- Architecture MVC légère et flexible
- Routing dynamique avec paramètres et regex
- Gestion des erreurs avec pages personnalisables (mode DEBUG/PRODUCTION)
- Configuration par environnement (dev/staging/prod)
- PSR-4 Autoloading via Composer
- Controller/View pattern avec injection de dépendances
- Patterns de sécurité prédéfinis pour validation
- Aucune dépendance externe (PHP pur)
La manière la plus rapide de démarrer avec Tekwork :
composer create-project tekwork/skeleton mon-projet
cd mon-projet✅ Projet prêt à l'emploi ! Structure complète, config auto-générée, exemples fonctionnels inclus.
👉 Voir tekwork/skeleton sur GitHub
Si vous préférez construire votre structure vous-même :
- PHP >= 8.0
- Composer
- Serveur web (Apache/Nginx) ou Laragon
# 1. Installer via Composer
composer require tekwork/framework
# 2. Créer votre structure
mkdir -p app/Controllers app/views public
# 3. Créer le fichier de configuration
cp vendor/tekwork/framework/config.example.php config.php
# 4. Éditer config.php selon votre environnement
nano config.php
# 5. Configurer votre serveur web (voir ci-dessous)server {
listen 80;
server_name monsite.local;
root /chemin/vers/projet/public;
index index.php;
location / {
try_files $uri $uri/ /index.php?$query_string;
}
location ~ \.php$ {
fastcgi_pass 127.0.0.1:9000;
fastcgi_index index.php;
include fastcgi_params;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
}
}RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ index.php [QSA,L]Le fichier config.php (à la racine) gère les environnements :
<?php
return [
// Mode debug
// true = Affichage détaillé des erreurs (développement)
// false = Pages d'erreur personnalisées (production)
'debug' => true,
// Chemin vers les vues d'erreur personnalisées
'error_views_path' => path_it(ROOT, 'app', 'views', 'errors'),
// Chemin du fichier de logs
'log_path' => path_it(ROOT, 'log', 'app_errors.log'),
];Important :
config.phpest dans.gitignore(jamais versionné)config.example.phpsert de modèle- Chaque environnement a sa propre configuration
projet/
├── src/ # Framework core (ne pas modifier)
│ ├── Router.php
│ ├── Road.php
│ ├── Dispatcher.php
│ ├── Controller.php
│ ├── View.php
│ ├── ErrorHandler.php
│ └── ...
├── app/ # Votre application
│ ├── bootstrap.php # Définition des routes
│ ├── Controllers/ # Vos contrôleurs
│ └── views/ # Vos templates
│ └── errors/ # Pages d'erreur personnalisées (404.php, 500.php)
├── public/ # Point d'entrée web
│ └── index.php
├── config.php # Configuration (non versionné)
└── config.example.php # Template de config
Dans app/bootstrap.php :
use Tekwork\Router;
use Tekwork\Road;
use Tekwork\Dispatcher;
use Tekwork\Request;
use Tekwork\SecurityPatterns;
$router = new Router();
// Route simple (page d'accueil)
$router->add(
new Road('', 'App\Controllers@HomeController:index', 'home')
);
// Route avec paramètre
$router->add(
(new Road('article/{:slug}', 'App\Controllers@ArticleController:show', 'article.show'))
->rule('slug', SecurityPatterns::SLUG)
);
// Route avec wildcard (multi-segments)
$router->add(
(new Road('docs/{:*path}', 'App\Controllers@DocsController:show', 'docs.show'))
->rule('path', SecurityPatterns::SAFE_PATH)
);
// Route avec valeurs par défaut
$router->add(
(new Road('blog/{:page}', 'App\Controllers@BlogController:index', 'blog'))
->rule('page', '[0-9]+')
->default('page', '1')
);
// Dispatching
$request = new Request();
$dispatcher = new Dispatcher($router);
$dispatcher->dispatch($request->get_uri());/ :
- Page d'accueil :
''(chaîne vide) - Autres routes :
'about','user/{:id}'
Dans app/Controllers/ArticleController.php :
<?php
namespace App\Controllers;
use Tekwork\Controller;
use Tekwork\View;
class ArticleController extends Controller
{
public function show(): void
{
// Accès aux paramètres de route
$slug = $this->params['slug'] ?? null;
// Créer une vue avec chemin absolu
$view = new View(path_it(ROOT, 'app', 'views', 'article.php'));
// Injecter des variables
$view->add_vars([
'title' => 'Mon Article',
'slug' => $slug,
'content' => 'Lorem ipsum...'
]);
// Rendu avec layout
$layout = path_it(ROOT, 'app', 'views', 'layout.php');
echo $this->render($layout, $view);
}
}Dans app/views/article.php :
<article>
<h1><?= htmlspecialchars($title) ?></h1>
<p><?= htmlspecialchars($content) ?></p>
</article>Dans app/views/layout.php :
<!DOCTYPE html>
<html lang="fr">
<head>
<meta charset="UTF-8">
<title>Mon Site</title>
</head>
<body>
<header>
<nav><!-- Menu --></nav>
</header>
<main>
<?= $content ?> <!-- Contenu de la vue injectée -->
</main>
<footer>
<p>© 2025</p>
</footer>
</body>
</html>Créez app/views/errors/404.php et 500.php :
<!DOCTYPE html>
<html lang="fr">
<head>
<title>404 - Page non trouvée</title>
</head>
<body>
<h1>Page non trouvée</h1>
<a href="/">Retour à l'accueil</a>
</body>
</html>Hiérarchie de recherche des vues d'erreur :
app/views/errors/{code}.php(ex:404.php,500.php)app/views/errors/error.php(vue générique)- Vue par défaut intégrée au framework
- ✅ Toujours échapper les sorties HTML :
htmlspecialchars($var) - ✅ Utiliser les SecurityPatterns pour valider les paramètres de route
- ✅ Mettre
debug = falseen production dansconfig.php - ✅ Ne JAMAIS versionner
config.php(déjà dans.gitignore) ⚠️ CSRF protection : pas encore implémentée (à faire manuellement)⚠️ Validation des inputs utilisateur : à implémenter dans vos contrôleurs
use Tekwork\SecurityPatterns;
SecurityPatterns::SAFE_PATH // [a-zA-Z0-9_\-\/]+
SecurityPatterns::SAFE_FILENAME // [a-zA-Z0-9_\-]+
SecurityPatterns::ALPHA_NUM // [a-zA-Z0-9]+
SecurityPatterns::SLUG // [a-zA-Z0-9\-]+Si vous découvrez une faille de sécurité, merci de la signaler de manière responsable via les Issues GitHub (en privé si possible).
// Dump formaté pour debug
dump($variable);
// Construction de chemins multi-OS
path_it('app', 'views', 'home.php'); // app/views/home.php (ou app\views\home.php sur Windows)$request = new Request();
// URI courante (sans slash initial)
$request->get_uri(); // "article/mon-slug"
// Segment par position (commence à 1)
$request->get_param(1); // "article"
$request->get_param(2); // "mon-slug"
// URLs
$request->get_base_url(); // "https://monsite.com"
$request->get_full_url(); // "https://monsite.com/article/mon-slug"
$request->get_host(); // "monsite.com" ou "monsite.com:8080"$router->url('article.show', ['slug' => 'mon-article']);
// Retourne : "article/mon-article"Format : Namespace@Classe:methode
Exemples :
App\Controllers@HomeController:index→App\Controllers\HomeController::index()Admin@UserController:edit→Admin\UserController::edit()
Le framework cherchera automatiquement :
Tekwork\→ dans/src/- Autre namespace → dans
/{namespace_lowercase}/
- Architecture MVC
- Routing avancé avec paramètres dynamiques
- ErrorHandler avec mode DEBUG/PRODUCTION
- Configuration par environnement
- Gestion des exceptions typées (NotFoundException)
- Middleware support (before/after)
- Session management sécurisée
- CSRF protection
- Database abstraction layer (PDO wrapper)
- Template engine (Twig/Blade)
- Logging system avancé
- CLI commands support
- Unit tests (PHPUnit)
- Validation des inputs utilisateur
- Rate limiting
Les contributions sont les bienvenues ! N'hésitez pas à :
- Fork le projet
- Créer une branche (
git checkout -b feature/amelioration) - Commit vos changements (
git commit -m 'Add: nouvelle feature') - Push vers la branche (
git push origin feature/amelioration) - Ouvrir une Pull Request
- Ce framework est un projet d'apprentissage extrait de TekNotes
- Il privilégie la simplicité et la compréhensibilité à la sur-architecture
- Parfait pour petits/moyens projets ou pour apprendre les concepts MVC
- Pour des projets critiques, préférez Laravel, Symfony ou Slim
- Extrait et adapté depuis TekNotes (système de documentation technique)
- Développé avec l'assistance de Claude AI (Anthropic)
- Auteur : Florian
Ce projet est sous licence MIT. Voir le fichier LICENSE pour plus de détails.
Philosophie : Minimaliste mais extensible. 🚀