Seb-Info

Gestion simple d’un ORM en PHP

Gestion simple d’un ORM en PHP

Objectif

L’ORM (Object Relational Mapping) est une technique qui permet de faire le lien entre les objets  et les lignes dans les tables d’une base de données. (ou fichiers : JSON, XML, etc.)

L’idée :

  • Chaque ligne de table ↔️ un objet PHP
  • Chaque colonne ↔️ un attribut de l’objetQu'est-ce qu'un ORM (Object-Relational Mapping) ?

On va créer un petit ORM manuel en utilisant PDO avec try / catch pour gérer les erreurs.


Principes clés

  • Hydratation : remplir automatiquement les attributs d’un objet à partir d’un tableau (résultat SQL).
  • Manager : classe qui contient les méthodes pour interagir avec la base (SELECT / INSERT / UPDATE…).
  • Exceptions : permettent d’attraper les erreurs (connexion, requêtes) pour éviter un plantage.

Exemple de base de données

CREATE TABLE roles (
    id INT AUTO_INCREMENT PRIMARY KEY,
    name VARCHAR(50) NOT NULL
);

INSERT INTO roles (name) VALUES ('Joueur'), ('Coach'), ('Président');

CREATE TABLE users (
    id INT AUTO_INCREMENT PRIMARY KEY,
    name VARCHAR(100) NOT NULL,
    email VARCHAR(150) NOT NULL UNIQUE,
    role_id INT NOT NULL,
    FOREIGN KEY (role_id) REFERENCES roles(id)
);

Classe User

<?php
class User {
    private int $id;
    private string $name;
    private string $email;
    private int $role_id;

    // --- Hydratation ---
    public function hydrate(array $data): void {
        foreach ($data as $key => $value) {
            $method = 'set' . ucfirst($key);
            if (method_exists($this, $method)) {
                $this->$method($value);
            }
        }
    }

    // --- Getters & Setters ---
    public function getId(): int { return $this->id; }
    public function setId(int $id): void { $this->id = $id; }

    public function getName(): string { return $this->name; }
    public function setName(string $name): void { $this->name = $name; }

    public function getEmail(): string { return $this->email; }
    public function setEmail(string $email): void { $this->email = $email; }

    public function getRole_id(): int { return $this->role_id; }
    public function setRole_id(int $role_id): void { $this->role_id = $role_id; }
}
?>

On va vérifier que la norme PS12 est appliqué :

Dans votre dossier projet dans le terminal VSC :

On va initialiser Composer qui permet de simplifier l’installation d’outil en PHP

composer init 

puis pour installer l’outil :

composer require –dev squizlabs/php_codesniffer

maintenant on a vérifier :

vendor/bin/phpcs –standard=PSR12 User.php

Le terminal doit afficher les erreurs par rapport à la norme PS12

Les corriger !

Pour corriger une partie automatiquement :

vendor/bin/phpcbf –standard=PSR12 User.php

Finir les corrections avec ChatGPT

Faire un commit : Application de la norme PSR12


Classe UserManager avec gestion d’exceptions

<?php
class UserManager {
    private PDO $pdo;

    public function __construct(PDO $pdo) {
        $this->pdo = $pdo;
    }

    // --- Ajouter un utilisateur ---
    public function add(User $user): bool {
        try {
            $sql = "INSERT INTO users (name, email, role_id) VALUES (:name, :email, :role_id)";
            $stmt = $this->pdo->prepare($sql);
            return $stmt->execute([
                ':name' => $user->getName(),
                ':email' => $user->getEmail(),
                ':role_id' => $user->getRole_id()
            ]);
        } catch (PDOException $e) {
            if ($e->getCode() == 23000) { 
                // 23000 = violation contrainte (ex: email déjà pris)
                echo "L'email existe déjà.";
            } else {
                echo "Erreur lors de l'ajout : " . $e->getMessage();
            }
            return false;
        }
    }

    // --- Trouver un utilisateur par son ID ---
    public function findById(int $id): ?User {
        try {
            $sql = "SELECT * FROM users WHERE id = :id";
            $stmt = $this->pdo->prepare($sql);
            $stmt->execute([':id' => $id]);
            $data = $stmt->fetch(PDO::FETCH_ASSOC);

            if ($data) {
                $user = new User();
                $user->hydrate($data);
                return $user;
            }
        } catch (PDOException $e) {
            echo "Erreur SQL : " . $e->getMessage();
        }
        return null;
    }

    // --- Récupérer tous les utilisateurs ---
    public function findAll(): array {
        $users = [];
        try {
            $stmt = $this->pdo->query("SELECT * FROM users ORDER BY name");
            while ($data = $stmt->fetch(PDO::FETCH_ASSOC)) {
                $user = new User();
                $user->hydrate($data);
                $users[] = $user;
            }
        } catch (PDOException $e) {
            echo "Erreur lors de la récupération : " . $e->getMessage();
        }
        return $users;
    }
}
?>

Remarque :

Le code 23000 que tu vois avec $e->getCode() est un SQLSTATE (code d’état SQL normalisé).

Signification

  • 23000 = Integrity constraint violation (violation d’une contrainte d’intégrité).

  • Cela recouvre plusieurs cas typiques :

    • Violation de clé primaire (tu essaies d’insérer une ligne avec un id déjà existant).

    • Violation de clé unique (UNIQUE) (ex : email déjà présent s’il est UNIQUE).

    • Violation de clé étrangère (FOREIGN KEY) (tu essaies de lier un enregistrement à un id parent inexistant).

    • Parfois des problèmes avec NOT NULL si on force une valeur nulle.

En pratique, avec MySQL/MariaDB, le cas le plus fréquent est l’insertion d’un doublon sur une colonne marquée UNIQUE.

Si tu veux savoir si c’est uniquement par exemple la clé primaire qui génère l’erreur par exemple, il faut utiliser  :


catch (PDOException $e) {
    if ($e->getCode() == "23000") {
        $info = $e->errorInfo;
        // $info[0] = SQLSTATE (23000)
        // $info[1] = code d'erreur MySQL spécifique
        // $info[2] = message MySQL complet

        if ($info[1] == 1062) {
            echo "Doublon (clé primaire ou clé unique).";
        } elseif ($info[1] == 1452) {
            echo "Violation de clé étrangère (FOREIGN KEY).";
        } else {
            echo "Violation d'une contrainte d'intégrité (autre).";
        }
    } else {
        // Pour toute autre erreur SQL
        echo "Erreur SQL : " . htmlspecialchars($e->getMessage());
    }
}

Les exceptions PDO sont interceptées pour :

  • Fournir un message clair à l’utilisateur.
  • Éviter de casser le script.
  • Différencier les erreurs (ex : doublon d’email avec code 23000).

Utilisation concrète

<?php
try {
    $pdo = new PDO("mysql:host=localhost;dbname=club_sport;charset=utf8", "root", "");
    $pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);

    $manager = new UserManager($pdo);

    // --- Ajouter un joueur ---
    $user = new User();
    $user->setName("Jean Dupont");
    $user->setEmail("jean.dupont@example.com");
    $user->setRole_id(1); // 1 = Joueur
    $manager->add($user);

    // --- Ajouter un coach ---
    $coach = new User();
    $coach->setName("Marie Coach");
    $coach->setEmail("marie.coach@example.com");
    $coach->setRole_id(2); // 2 = Coach
    $manager->add($coach);

    // --- Afficher tous les membres ---
    $users = $manager->findAll();
    foreach ($users as $u) {
        echo $u->getName() . " (" . $u->getEmail() . ")<br>";
    }

} catch (PDOException $e) {
    // Si la connexion échoue
    echo "Impossible de se connecter à la base : " . $e->getMessage();
}
?>

Points pédagogiques pour BTS SIO SLAM

  • Un objet ↔ une ligne SQL : l’ORM simplifie la manipulation des données.
  • Hydratation : remplit automatiquement un objet à partir d’un tableau PDO.
  • Manager : centralise toutes les requêtes SQL.
  • try / catch : sécurise le code, empêche les messages d’erreur bruts en production.

TD — Mini-ORM en PHP avec PDO, Exceptions et Git

Niveau : BTS SIO SLAM (2e année)

Objectifs :
Créer une application PHP simple qui gère des équipes d’un club sportif en utilisant :

  • PDO pour accéder à MySQL avec try/catch pour gérer les erreurs
  • Un mini-ORM (classes + hydratation d’objets)
  • Git pour versionner le code et travailler proprement

Initialiser votre dépôt Git (vous pouvez travailler avec VSC)

  1. Créez un dossier de projet, ex. club_sport
  2. Ouvrez un terminal dans ce dossier et lancez :
git init
git branch -M main
  1. Créez un dépôt vide sur GitHub (nom ex : club_sport_orm).
  2. Ajoutez le dépôt distant :
git remote add origin https://github.com/<votre_user>/club_sport_orm.git
  1. Premier commit :
git add .
git commit -m "Initialisation du projet"
git push -u origin main

Étape 1 — Créer la base de données

Ajoute ce fichier scriptStructures.sql dans ton projet


CREATE DATABASE IF NOT EXISTS club_sport CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci;
USE club_sport;

-- Table des rôles
CREATE TABLE IF NOT EXISTS roles (
  id INT AUTO_INCREMENT PRIMARY KEY,
  name VARCHAR(50) NOT NULL
);

INSERT INTO roles (name) VALUES ('Joueur'), ('Coach'), ('Président');

-- Table des membres
CREATE TABLE IF NOT EXISTS users (
  id INT AUTO_INCREMENT PRIMARY KEY,
  name VARCHAR(100) NOT NULL,
  email VARCHAR(150) NOT NULL UNIQUE,
  role_id INT NOT NULL,
  CONSTRAINT fk_users_role FOREIGN KEY (role_id) REFERENCES roles(id)
);

-- Table des équipes
CREATE TABLE IF NOT EXISTS equipes (
  id INT AUTO_INCREMENT PRIMARY KEY,
  nom VARCHAR(100) NOT NULL,
  niveau ENUM('Débutant','Confirmé') NOT NULL,
  coach_id INT NOT NULL,
  CONSTRAINT fk_equipes_coach FOREIGN KEY (coach_id) REFERENCES users(id)
);

-- Table d'association joueurs ↔ équipes
CREATE TABLE IF NOT EXISTS joueurs_equipes (
  equipe_id INT NOT NULL,
  joueur_id INT NOT NULL,
  PRIMARY KEY (equipe_id, joueur_id),
  CONSTRAINT fk_je_equipe FOREIGN KEY (equipe_id) REFERENCES equipes(id),
  CONSTRAINT fk_je_joueur FOREIGN KEY (joueur_id) REFERENCES users(id)
);

Git :

git add .
git commit -m "Ajout du script SQL pour créer la base de données"
git push

Une fois le fichier .sql fait charge le dans MySQLWorkBench et execute le !

Cela devrait créer la structure de ta BDD. Maintenant active ta base de données en double cliquant dessus !

Elle doit apparaitre en surbrillance !

Étape 2 — Ajouter des données d’exemple

Idem ajoute ce fichier ( scriptDonnees.sql) à ton projet

INSERT INTO users (name, email, role_id) VALUES
  ('Jean Dupont', 'jean.dupont@club.fr', 1),
  ('Alice Martin', 'alice.martin@club.fr',1),
  ('Marie Coach', 'marie.coach@club.fr', 2),
  ('Paul Coach', 'paul.coach@club.fr', 2),
  ('Jacques Président','jacques.pres@club.fr',3);

Git :

git add .
git commit -m "Ajout d'un script SQL pour remplir les tables avec des exemples"
git push

Vous devez avoir ceci  :

Idem chargé ce fichier depuis MySQLWorkbench et lancer ce script pour ajouter les données dans vos tables.

Étape 3 — Créer les classes PHP (Entités)

Fichier : classes/User.php

<?php
class User {
    private int $id;
    private string $name;
    private string $email;
    private int $role_id;

    public function hydrate(array $data): void {
        foreach ($data as $key => $value) {
            $method = 'set' . ucfirst($key);
            if (method_exists($this, $method)) {
                $this->$method($value);
            }
        }
    }

    public function getId(): int { return $this->id; }
    public function setId(int $id): void { $this->$id = $id; }

    public function getName(): string { return $this->name; }
    public function setName(string $name): void { $this->name = $name; }

    public function getEmail(): string { return $this->email; }
    public function setEmail(string $email): void { $this->email = $email; }

    public function getRole_id(): int { return $this->role_id; }
    public function setRole_id(int $role_id): void { $this->role_id = $role_id; }
}

On peut vérifier que la norme PSR12 est appliqué !

Dans votre dossier dans le terminal VSC

composer init

On installe l’outil qui vérifie que les normes sont respectées.

composer require –dev squizlabs/php_codesniffer

On peut après l’utiliser :

vendor/bin/phpcs –standard=PSR12 User.php

On corrige les erreurs !

Pour corriger une partie automatiquement :

vendor/bin/phpcbf –standard=PSR12 User.php

Après avoir appliqué la norme PSR12 faire un commit : « Application de la norme PSR12 »

Fichier : classes/Equipe.php

<?php
require_once __DIR__ . '/User.php';

class Equipe {
    private int $id;
    private string $nom;
    private string $niveau;
    private int $coach_id;
    /** @var User[] */
    private array $joueurs = [];

    public function hydrate(array $data): void {
        foreach ($data as $key => $value) {
            $method = 'set' . ucfirst($key);
            if (method_exists($this, $method)) {
                $this->$method($value);
            }
        }
    }

    public function getId(): int { return $this->id; }
    public function setId(int $id): void { $this->id = $id; }

    public function getNom(): string { return $this->nom; }
    public function setNom(string $nom): void { $this->nom = $nom; }

    public function getNiveau(): string { return $this->niveau; }
    public function setNiveau(string $niveau): void { $this->niveau = $niveau; }

    public function getCoach_id(): int { return $this->coach_id; }
    public function setCoach_id(int $coach_id): void { $this->coach_id = $coach_id; }

    public function getJoueurs(): array { return $this->joueurs; }
    public function setJoueurs(array $joueurs): void { $this->joueurs = $joueurs; }
}

Git :

git add classes/User.php classes/Equipe.php
git commit -m "Ajout des classes User et Equipe avec hydratation"
git push

Étape 4 — Créer le manager EquipeManager avec try/catch

Fichier : classes/EquipeManager.php

<?php
require_once __DIR__ . '/Equipe.php';

class EquipeManager {
    private PDO $pdo;

    public function __construct(PDO $pdo) {
        $this->pdo = $pdo;
    }

    public function add(Equipe $equipe): int {
        try {
            $check = $this->pdo->prepare("SELECT id FROM users WHERE id = :id AND role_id = 2");
            $check->execute([':id' => $equipe->getCoach_id()]);
            if (!$check->fetch()) {
                throw new Exception("Coach inexistant ou non autorisé.");
            }

            $stmt = $this->pdo->prepare("INSERT INTO equipes (nom, niveau, coach_id) VALUES (:nom, :niveau, :coach_id)");
            $stmt->execute([
                ':nom' => $equipe->getNom(),
                ':niveau' => $equipe->getNiveau(),
                ':coach_id' => $equipe->getCoach_id()
            ]);
            return (int)$this->pdo->lastInsertId();

        } catch (PDOException $e) {
            throw new Exception("Erreur BDD (add): " . $e->getMessage(), 0, $e);
        }
    }

    public function addJoueurToEquipe(int $equipeId, int $joueurId): void {
        try {
            $check = $this->pdo->prepare("SELECT id FROM users WHERE id = :id AND role_id = 1");
            $check->execute([':id' => $joueurId]);
            if (!$check->fetch()) {
                throw new Exception("Le joueur n'existe pas ou n'est pas de rôle Joueur.");
            }

            $stmt = $this->pdo->prepare("INSERT INTO joueurs_equipes (equipe_id, joueur_id) VALUES (:e, :j)");
            $stmt->execute([':e' => $equipeId, ':j' => $joueurId]);

        } catch (PDOException $e) {
            throw new Exception("Erreur BDD (addJoueurToEquipe): " . $e->getMessage(), 0, $e);
        }
    }

    public function findByIdWithPlayers(int $id): ?Equipe {
        try {
            $stmt = $this->pdo->prepare("SELECT * FROM equipes WHERE id = :id");
            $stmt->execute([':id' => $id]);
            $row = $stmt->fetch(PDO::FETCH_ASSOC);

            if (!$row) return null;

            $e = new Equipe();
            $e->hydrate($row);

            $stmt2 = $this->pdo->prepare("
                SELECT u.* FROM joueurs_equipes je
                JOIN users u ON u.id = je.joueur_id
                WHERE je.equipe_id = :id
            ");
            $stmt2->execute([':id' => $id]);

            $joueurs = [];
            while ($urow = $stmt2->fetch(PDO::FETCH_ASSOC)) {
                $u = new User();
                $u->hydrate($urow);
                $joueurs[] = $u;
            }
            $e->setJoueurs($joueurs);

            return $e;

        } catch (PDOException $e) {
            throw new Exception("Erreur BDD (findByIdWithPlayers): " . $e->getMessage(), 0, $e);
        }
    }
}

Git :

git add classes/EquipeManager.php
git commit -m "Ajout du manager Equipe avec gestion d'exceptions"
git push

Étape 5 — Script de test

Fichier : public/test_equipes.php

<?php
require_once __DIR__ . '/../classes/User.php';
require_once __DIR__ . '/../classes/Equipe.php';
require_once __DIR__ . '/../classes/EquipeManager.php';

try {
    $pdo = new PDO("mysql:host=localhost;dbname=club_sport;charset=utf8mb4", "root", "");
    $pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);

    $manager = new EquipeManager($pdo);

    // Créer une équipe
    $e = new Equipe();
    $e->setNom("Les Lions");
    $e->setNiveau("Confirmé");
    $e->setCoach_id(3); // Marie Coach
    $idEquipe = $manager->add($e);
    echo "<p>Equipe créée : ID ".$idEquipe."</p>";

    // Ajouter des joueurs
    $manager->addJoueurToEquipe($idEquipe, 1); // Jean Dupont
    $manager->addJoueurToEquipe($idEquipe, 2); // Alice Martin

    // Afficher l'équipe avec ses joueurs
    $loaded = $manager->findByIdWithPlayers($idEquipe);
    echo "<h3>".$loaded->getNom()." (".$loaded->getNiveau().")</h3>";
    echo "<ul>";
    foreach($loaded->getJoueurs() as $j){
        echo "<li>".$j->getName()." - ".$j->getEmail()."</li>";
    }
    echo "</ul>";

} catch(Exception $e) {
    echo "<p style='color:red'>Erreur : ".htmlspecialchars($e->getMessage())."</p>";
}

Git :

git add public/test_equipes.php
git commit -m "Ajout du script de test pour créer une équipe et associer des joueurs"
git push

Étape 6 — Cas à tester

  • ✅ Créer une équipe avec un coach existant → doit s’insérer
  • ❌ Créer avec un coach inexistant → message d’erreur
  • ❌ Ajouter un joueur inexistant → message d’erreur
  • ❌ Ajouter un utilisateur qui n’est pas un joueur → message d’erreur

Étape 7 — Bonnes pratiques Git

  • Commitez souvent : 1 commit = 1 fonctionnalité claire.
  • Poussez régulièrement sur GitHub pour sauvegarder.
  • Utilisez des branches pour les nouvelles fonctionnalités :
    git checkout -b feature/affichage_equipes
    
    

Étape 8 — Commentaires & Docblocks

Pourquoi documenter ?

  • Clarifie l’intention et les préconditions d’une méthode (contrats d’usage).
  • Aide les IDE (VS Code / PhpStorm) pour l’auto-complétion et la navigation.
  • Permet de générer une doc HTML via des outils (phpDocumentor, Doctum, etc.).

Rappels de syntaxe (PHPDoc)

Un docblock se place juste au-dessus d’une classe/méthode/attribut :

/**
 * Brève description.
 *
 * Description détaillée (optionnelle).
 *
 * @tag1 ...
 * @tag2 ...
 */

Tags les plus utilisés :

  • @param type $nom : décrit un paramètre
  • @return type : type de retour
  • @throws \ExceptionType : exception potentielle
  • @var type : type d’un attribut
  • @author, @version (optionnels)

Exemple appliqué à votre TD (classe User)

<?php
declare(strict_types=1);

/**
 * Représente un utilisateur du club (entité métier).
 */
class User
{
    /**
     * Identifiant unique.
     * @var int
     */
    private int $id;

    /**
     * Nom complet.
     * @var string
     */
    private string $name;

    /**
     * Adresse e-mail.
     * @var string
     */
    private string $email;

    /**
     * Identifiant du rôle (clé étrangère vers la table roles).
     * @var int
     */
    private int $roleId;

    /**
     * Hydrate l'objet à partir d'un tableau associatif.
     *
     * @param array $data Tableau [cle => valeur] (ex. issu d'un fetch PDO)
     * @return void
     */
    public function hydrate(array $data): void
    {
        foreach ($data as $key => $value) {
            $method = 'set' . ucfirst($key);
            if (method_exists($this, $method)) {
                $this->$method($value);
            }
        }
    }

    /** @return int */
    public function getId(): int { return $this->id; }

    /** @param int $id */
    public function setId(int $id): void { $this->id = $id; }

    /** @return string */
    public function getName(): string { return $this->name; }

    /** @param string $name */
    public function setName(string $name): void { $this->name = $name; }

    /** @return string */
    public function getEmail(): string { return $this->email; }

    /** @param string $email */
    public function setEmail(string $email): void { $this->email = $email; }

    /** @return int */
    public function getRoleId(): int { return $this->roleId; }

    /** @param int $roleId */
    public function setRoleId(int $roleId): void { $this->roleId = $roleId; }
}

Exemple appliqué au UserManager (PDO + exceptions)

<?php
declare(strict_types=1);

/**
 * Service d'accès aux utilisateurs (CRUD).
 */
class UserManager
{
    private \PDO $pdo;

    /**
     * @param \PDO $pdo Connexion PDO (injectée)
     */
    public function __construct(\PDO $pdo)
    {
        $this->pdo = $pdo;
    }

    /**
     * Insère un nouvel utilisateur.
     *
     * @param User $user Entité à persister
     * @return bool True si insertion OK
     * @throws \PDOException En cas d'erreur SQL
     */
    public function add(User $user): bool
    {
        try {
            $sql = "INSERT INTO users (name, email, role_id) VALUES (:name, :email, :role_id)";
            $stmt = $this->pdo->prepare($sql);
            return $stmt->execute([
                ':name'    => $user->getName(),
                ':email'   => $user->getEmail(),
                ':role_id' => $user->getRoleId(),
            ]);
        } catch (\PDOException $e) {
            // 23000 = violation d'intégrité (clé unique / clé étrangère)
            if ($e->getCode() === '23000') {
                $info = $e->errorInfo;
                if (($info[1] ?? null) === 1062) {
                    // Doublon (clé unique)
                    throw new \PDOException("E-mail déjà utilisé (doublon).", 1062, $e);
                }
                if (($info[1] ?? null) === 1452) {
                    // Clé étrangère non respectée
                    throw new \PDOException("Rôle inexistant (violation de clé étrangère).", 1452, $e);
                }
            }
            throw $e; // remonter l'erreur si non gérable ici
        }
    }

    /**
     * Récupère un utilisateur par son identifiant.
     *
     * @param int $id Identifiant
     * @return User|null L'entité ou null si non trouvée
     */
    public function findById(int $id): ?User
    {
        $stmt = $this->pdo->prepare("SELECT * FROM users WHERE id = :id");
        $stmt->execute([':id' => $id]);
        $row = $stmt->fetch(\PDO::FETCH_ASSOC);
        if (!$row) {
            return null;
        }
        $u = new User();
        $u->hydrate($row);
        return $u;
    }
}

Travail  à faire

  1. Ajouter des docblocks complets à vos classes User, Role, Equipe, UserManager, etc. (toutes les méthodes publiques au minimum).
  2. Documenter précisément :
    • le rôle de la classe/méthode,
    • les paramètres (@param type + signification),
    • le type de retour (@return),
    • les exceptions possibles (@throws),
    • les attributs non triviaux (@var).
  3. Dans les blocs catch, expliquer en 1–2 lignes ce que vous traitez (ex. code SQLState 23000, cas 1062/1452, stratégie choisie).
  4. Vérifier la cohérence types PHP ↔ types PHPDoc (PSR-12 recommandé).

Checklist d’auto-évaluation

  • Chaque fichier PHP commence par declare(strict_types=1); et un namespace cohérent.
  • Toutes les méthodes publiques ont un docblock @param/@return exact.
  • Les exceptions métiers ou PDO sont documentées avec @throws.
  • Les parties « non évidentes » du code ont un court commentaire au-dessus (1–2 lignes max). Dire pourquoi vous avez fait ça ! Pas ce que vous faites !
  • Le projet passe au vert avec phpcs (PSR-12) et les types PHPDoc correspondent au code.

Outils utiles

  • Vérification PSR-12 : composer require --dev squizlabs/php_codesniffer puis vendor/bin/phpcs --standard=PSR12 src/
  • Correction auto : vendor/bin/phpcbf --standard=PSR12 src/
  • Génération de doc : phpDocumentor / Doctum (facultatif pour ce TD).

Ce contenu est réservé aux membres du site. Si vous êtes un utilisateur existant, veuillez vous connecter. Les nouveaux utilisateurs peuvent s'inscrire ci-dessous.

Connexion pour les utilisateurs enregistrés
   
Nouvel utilisateur ?
*Champ requis
Powered by WP-Members