Aller au contenu principal

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 <?php et <?=
  • 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

  1. Standards PSR

    • Refactorisez votre code selon PSR-12
    • Organisez avec namespaces
    • Utilisez l'autoloading
  2. Sécurité

    • Protégez contre XSS
    • Validez toutes les entrées
    • Utilisez password_hash
  3. Organisation

    • Séparez en MVC
    • Créez une structure de dossiers claire
    • Utilisez des namespaces
  4. Configuration

    • Créez un fichier de configuration
    • Séparez dev/prod
    • Utilisez des variables d'environnement
  5. Documentation

    • Ajoutez PHPDoc à toutes vos fonctions
    • Documentez vos classes
    • Créez un README

Quiz

  1. Que signifie PSR ?

    • PHP Standard Rules
    • PHP Standards Recommendations
    • PHP Style Rules
  2. Comment protéger contre XSS ?

    • Utiliser md5()
    • Utiliser htmlspecialchars()
    • Utiliser trim()
  3. Comment hacher un mot de passe en PHP ?

    • md5()
    • password_hash()
    • sha1()
  4. Que fait l'autoloading ?

    • Charge automatiquement les classes
    • Charge automatiquement les classes
    • Compile le code
  5. 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 :

  1. Structure PSR-12

    • Respecter les standards de codage
    • Indentation, nommage, formatage
    • Namespaces appropriés
  2. Séparation MVC

    • Séparer logique, données, affichage
    • Créer des controllers
    • Créer des models
    • Créer des views
  3. Sécurité

    • Protection XSS partout
    • Validation de toutes les entrées
    • Protection CSRF sur formulaires
    • Mots de passe hashés
  4. Organisation

    • Structure de dossiers claire
    • Autoloading configuré
    • Configuration externalisée
  5. 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.