Module PHP.12 – Bonnes pratiques
Objectif
Appliquer les bonnes pratiques PHP : standards PSR, séparation de la logique, sécurité de base, et organisation professionnelle du code.
Théorie
PSR (PHP Standards Recommendations)
Les PSR sont des standards de la communauté PHP.
PSR-1 : Basic Coding Standard
- Utiliser
<?phpet<?= - Encodage UTF-8 sans BOM
- Classes en PascalCase
- Méthodes en camelCase
- Constantes en UPPER_CASE
PSR-12 : Extended Coding Style
- Indentation : 4 espaces
- Pas de tabulation
- Ligne max 120 caractères
- Accolades sur nouvelle ligne pour classes/méthodes
Exemple PSR-12 :
<?php
declare(strict_types=1);
namespace MonProjet;
class MaClasse
{
private const CONSTANTE = 'valeur';
public function maMethode(): string
{
return self::CONSTANTE;
}
}
Séparation de la logique
Structure MVC (Model-View-Controller) :
projet/
├── public/
│ └── index.php # Point d'entrée
├── src/
│ ├── Controllers/ # Logique métier
│ ├── Models/ # Données
│ └── Views/ # Affichage
├── config/ # Configuration
└── vendor/ # Dépendances
Séparation des responsabilités :
// ❌ Mauvais : Tout mélangé
<?php
$nom = $_POST['nom'];
echo "<h1>Bonjour $nom</h1>";
$db->query("INSERT INTO users...");
?>
// ✅ Bon : Séparé
// Controller
$nom = $_POST['nom'];
$user = new User($nom);
$user->save();
// View
<?php include 'header.php'; ?>
<h1>Bonjour <?= $user->getNom() ?></h1>
<?php include 'footer.php'; ?>
Sécurité de base
1. Protection XSS (Cross-Site Scripting) :
// ❌ Dangereux
echo $_GET['nom'];
// ✅ Sécurisé
echo htmlspecialchars($_GET['nom'], ENT_QUOTES, 'UTF-8');
// Ou avec fonction helper
function e($string) {
return htmlspecialchars($string, ENT_QUOTES, 'UTF-8');
}
echo e($_GET['nom']);
2. Protection SQL Injection :
// ❌ Dangereux
$query = "SELECT * FROM users WHERE id = " . $_GET['id'];
// ✅ Sécurisé avec PDO
$stmt = $pdo->prepare("SELECT * FROM users WHERE id = ?");
$stmt->execute([$_GET['id']]);
3. Validation des entrées :
// Toujours valider
$email = filter_var($_POST['email'], FILTER_VALIDATE_EMAIL);
if (!$email) {
throw new Exception("Email invalide");
}
4. Protection CSRF :
// Générer un token
$_SESSION['csrf_token'] = bin2hex(random_bytes(32));
// Dans le formulaire
<input type="hidden" name="csrf_token" value="<?= $_SESSION['csrf_token'] ?>">
// Vérifier
if ($_POST['csrf_token'] !== $_SESSION['csrf_token']) {
throw new Exception("Token CSRF invalide");
}
5. Mots de passe :
// ❌ Jamais en clair
$mdp = $_POST['password'];
$hash = md5($mdp); // Faible
// ✅ Hash sécurisé
$hash = password_hash($_POST['password'], PASSWORD_DEFAULT);
// Vérifier
if (password_verify($mdp_saisi, $hash_stocke)) {
// Mot de passe correct
}
Organisation du code
Autoloading (PSR-4) :
// composer.json
{
"autoload": {
"psr-4": {
"MonProjet\\": "src/"
}
}
}
Utilisation :
// Avant autoload
require_once 'src/Models/User.php';
require_once 'src/Controllers/UserController.php';
// Avec autoload
require 'vendor/autoload.php';
use MonProjet\Models\User;
use MonProjet\Controllers\UserController;
Structure de fichiers :
src/
├── Controllers/
│ └── UserController.php
├── Models/
│ └── User.php
├── Views/
│ └── user/
│ └── index.php
├── Services/
│ └── EmailService.php
└── Utils/
└── helpers.php
Namespaces :
namespace MonProjet\Controllers;
use MonProjet\Models\User;
use MonProjet\Services\EmailService;
class UserController
{
// ...
}
Configuration
Fichier de configuration :
// config/database.php
return [
'host' => 'localhost',
'dbname' => 'monapp',
'user' => 'root',
'pass' => ''
];
// Utilisation
$config = require 'config/database.php';
Variables d'environnement :
// .env (ne pas commiter)
DB_HOST=localhost
DB_NAME=monapp
DB_USER=root
DB_PASS=
// Charger avec une bibliothèque (vlucas/phpdotenv)
$dotenv = Dotenv\Dotenv::createImmutable(__DIR__);
$dotenv->load();
$host = $_ENV['DB_HOST'];
Documentation
PHPDoc :
/**
* Calcule la moyenne d'un tableau de notes
*
* @param array<int> $notes Tableau de notes
* @return float|null Moyenne ou null si tableau vide
* @throws InvalidArgumentException Si notes invalides
*/
function calculerMoyenne(array $notes): ?float
{
if (empty($notes)) {
return null;
}
return array_sum($notes) / count($notes);
}
Exercice
-
Standards PSR
- Refactorisez votre code selon PSR-12
- Organisez avec namespaces
- Utilisez l'autoloading
-
Sécurité
- Protégez contre XSS
- Validez toutes les entrées
- Utilisez password_hash
-
Organisation
- Séparez en MVC
- Créez une structure de dossiers claire
- Utilisez des namespaces
-
Configuration
- Créez un fichier de configuration
- Séparez dev/prod
- Utilisez des variables d'environnement
-
Documentation
- Ajoutez PHPDoc à toutes vos fonctions
- Documentez vos classes
- Créez un README
Quiz
-
Que signifie PSR ?
- PHP Standard Rules
- PHP Standards Recommendations
- PHP Style Rules
-
Comment protéger contre XSS ?
- Utiliser md5()
- Utiliser htmlspecialchars()
- Utiliser trim()
-
Comment hacher un mot de passe en PHP ?
- md5()
- password_hash()
- sha1()
-
Que fait l'autoloading ?
- Charge automatiquement les classes
- Charge automatiquement les classes
- Compile le code
-
Où stocker les mots de passe de base de données ?
- Dans le code
- Dans un fichier .env (non commité)
- Dans un fichier config.php (commité)
Mini défi
Mission : Refactoriser un projet selon les bonnes pratiques
Prenez un projet PHP existant (ou créez-en un) et refactorisez-le :
Améliorations à apporter :
-
Structure PSR-12
- Respecter les standards de codage
- Indentation, nommage, formatage
- Namespaces appropriés
-
Séparation MVC
- Séparer logique, données, affichage
- Créer des controllers
- Créer des models
- Créer des views
-
Sécurité
- Protection XSS partout
- Validation de toutes les entrées
- Protection CSRF sur formulaires
- Mots de passe hashés
-
Organisation
- Structure de dossiers claire
- Autoloading configuré
- Configuration externalisée
-
Documentation
- PHPDoc complet
- README avec instructions
- Commentaires pertinents
Critères :
- ✅ Code conforme PSR-12
- ✅ Architecture MVC claire
- ✅ Sécurité renforcée
- ✅ Documentation complète
- ✅ Code maintenable et professionnel
Objectif : Appliquer toutes les bonnes pratiques pour créer du code professionnel et maintenable.
Validation : Vous pouvez passer au module suivant quand votre code respecte les standards et bonnes pratiques.