Cours PHP Complet 🐘

Les 12 chapitres essentiels — de la syntaxe de base à la POO et aux bases de données, avec exemples et quiz

12
Chapitres
100+
Exemples de code
PHP 8.x
Version
A1→C2
Niveaux

CHAPITRE 01

Introduction et premier script

🐘 Hello World

// PHP = Hypertext Preprocessor — langage serveur
echo « Bonjour le monde ! »;

// Afficher avec formatage
print_r($variable); // Affiche un array/objet lisiblement
var_dump($variable); // Affiche type + valeur (debug)
?>

PHP s'exécute côté serveur. Le navigateur ne reçoit que le HTML résultant. Chaque fichier PHP commence par . Le tag de fermeture ?> est optionnel (et déconseillé) dans les fichiers 100% PHP.

⚙️ Comment ça marche
Caractéristique PHP
Exécution Côté serveur — Apache, Nginx, ou built-in server
Typage Dynamique (types déclarés optionnels depuis PHP 7+)
Usage principal Sites web dynamiques, APIs, WordPress, Laravel
Fichiers .php
Serveur local php -S localhost:8000
Convention $camelCase pour variables, PascalCase pour classes
🧠 Quiz
Le code PHP est-il visible par l'utilisateur dans le navigateur ?
Non. PHP s'exécute sur le serveur. Le navigateur reçoit uniquement le HTML/CSS/JS généré. Le code source PHP n'est jamais envoyé au client.

CHAPITRE 02

Variables et types

📦 Variables et types de données
// Toutes les variables commencent par $
$nom = « Alice »; // string
$age = 25; // int
$taille = 1.75; // float
$actif = true; // bool
$rien = null; // null
$fruits = [« pomme », « banane »]; // array

// Vérifier le type
gettype($nom); // « string »
is_string($nom); // true
is_int($age); // true
is_array($fruits); // true
isset($nom); // true (existe et pas null)
empty($nom); // false (non vide)

📝 Strings
// Guillemets doubles — interprètent les variables
$nom = « Alice »;
echo « Bonjour $nom ! »; // Bonjour Alice !
echo « Age:  »; // Accolades pour les expressions

// Guillemets simples — texte brut (pas d'interpolation)
echo 'Bonjour $nom !'; // Bonjour $nom !

// Concaténation avec le point (.)
echo « Bonjour «  . $nom .  » ! »;

// Fonctions string
strlen($nom); // 5
strtoupper($nom); // « ALICE »
strtolower($nom); // « alice »
trim( » hello « ); // « hello »
str_replace(« A », « a », $nom); // « alice »
substr($nom, 0, 3); // « Ali »
str_contains($nom, « lic »); // true (PHP 8+)
str_starts_with($nom, « A »); // true (PHP 8+)
explode(« , », « a,b,c »); // [« a », « b », « c »]
implode(« , », $arr); // « a,b,c »

🔄 Casting et constantes
// Casting explicite
$n = (int) « 42 »; // 42
$s = (string) 42; // « 42 »
$f = (float) « 3.14 »; // 3.14
$b = (bool) «  »; // false
intval(« 42abc »); // 42

// Constantes (immuables)
const PI = 3.14159;
define(« MAX », 100); // Alternative (ancienne syntaxe)

Piège courant : PHP fait du type juggling (conversion implicite). 0 == « abc » était true avant PHP 8 ! Depuis PHP 8, c'est corrigé, mais utilisez toujours === pour les comparaisons.

🧠 Quiz
Différence entre guillemets simples et doubles en PHP ?
Doubles «  » = interprètent les variables ("Hello $nom"). Simples  » = texte brut, pas d'interpolation. Les simples sont légèrement plus rapides.

CHAPITRE 03

Opérateurs et expressions

⚖️ Comparaison : == vs ===
// == (loose) — compare les VALEURS avec conversion
0 == « 0 » // true
1 == true // true
«  » == false // true
«  » == 0 // true ⚠️

// === (strict) — compare VALEUR et TYPE
0 === « 0 » // false ✅
1 === true // false ✅

// Spaceship operator (PHP 7+)
1 <=> 2 // -1 (inférieur)
2 <=> 2 // 0 (égal)
3 <=> 2 // 1 (supérieur)

// Null coalescing (??) — valeur par défaut si null
$nom = $_GET['nom'] ?? « Inconnu »;

// Null coalescing assignment (??=)
$x ??= « défaut »; // Assigne seulement si $x est null

// Nullsafe operator (?->) (PHP 8+)
$ville = $user?->getAddress()?->city;
// Retourne null au lieu de crash si $user ou getAddress() est null

Règle d'or : utilisez TOUJOURS === (comparaison stricte). L'opérateur == fait des conversions implicites imprévisibles et est la source de bugs subtils en PHP.

CHAPITRE 04

Structures conditionnelles

🔀 if / else / switch / match
// if / else
if ($age < 18) elseif ($age < 65) else

// switch (comparaison loose ==)
switch ($jour)

// match (PHP 8+) — comparaison STRICTE, retourne une valeur
$result = match($status) ;

match > switch. Depuis PHP 8, préférez match : comparaison stricte (===), pas besoin de break, retourne une valeur, et lance une erreur si aucun cas ne correspond (sauf avec default).

⚡ Valeurs falsy en PHP
// Toutes ces valeurs sont considérées comme false :
false
0 // int zéro
0.0 // float zéro
«  » // chaîne vide
« 0 » // ⚠️ la chaîne « 0 » est falsy en PHP ![] // array vide
null

CHAPITRE 05

Les boucles

🔁 for, foreach, while
// for classique
for ($i = 0; $i < 5; $i++)

// foreach — LE plus utilisé en PHP
$fruits = [« pomme », « banane », « cerise »];
foreach ($fruits as $fruit)

// foreach avec clé
$ages = [« Alice » => 25, « Bob » => 30];
foreach ($ages as $nom => $age)

// while
while ($i < 10)

// do-while
do while ($i < 10);

CHAPITRE 06

Les tableaux (Arrays)

📋 Arrays indexés et associatifs
// Array indexé (numéroté automatiquement)
$fruits = [« pomme », « banane », « cerise »];
$fruits[0]; // « pomme »

// Array associatif (clé => valeur) — comme un dictionnaire
$user = [
« nom » => « Alice »,
« age » => 25,
« email » => « alice@mail.com »,
];
$user[« nom »]; // « Alice »

En PHP, Array = tout à la fois. Contrairement à d'autres langages, un seul type array sert de list, dict, set, stack, queue. C'est à la fois sa force et sa confusion.

🔧 Fonctions array essentielles
Fonction Action Exemple
count() Nombre d'éléments count($arr)
array_push() Ajouter à la fin $arr[] = « x » (raccourci)
array_pop() Retirer le dernier array_pop($arr)
array_shift() Retirer le premier array_shift($arr)
array_unshift() Ajouter au début array_unshift($arr, « x »)
in_array() Vérifier l'existence in_array(« x », $arr, true)
array_key_exists() Clé existe ? array_key_exists(« nom », $arr)
array_merge() Fusionner array_merge($a, $b)
array_keys() Toutes les clés array_keys($arr)
array_values() Toutes les valeurs array_values($arr)
sort() Trier (réindexe) sort($arr)
array_slice() Extraire une portion array_slice($arr, 0, 3)
array_unique() Dédupliquer array_unique($arr)
⚡ map, filter, reduce
$nombres = [1, 2, 3, 4, 5];

// array_map — transforme chaque élément
$doubles = array_map(fn($n) => $n * 2, $nombres);
// [2, 4, 6, 8, 10]

// array_filter — garde ceux qui passent le test
$pairs = array_filter($nombres, fn($n) => $n % 2 === 0);
// [2, 4]

// array_reduce — accumule en une valeur
$somme = array_reduce($nombres, fn($acc, $n) => $acc + $n, 0);
// 15

// Destructurer (PHP 7.1+)[$a, $b, $c] = [1, 2, 3];[« nom » => $nom, « age » => $age] = $user;

🧠 Quiz
Différence entre array_map et array_filter ?
array_map = transforme chaque élément (change les valeurs). array_filter = sélectionne les éléments (garde ou exclut selon un test).

CHAPITRE 07

Fonctions

🔧 Déclarer et typer des fonctions
// Fonction basique
function saluer(string $nom): string

// Paramètre optionnel avec valeur par défaut
function puissance(float $base, int $exp = 2): float

// Nullable (?type)
function trouver(int $id): ?string

// Union types (PHP 8+)
function format(string|int $value): string

// void — ne retourne rien
function log(string $msg): void

⚡ Arrow functions et arguments nommés
// Arrow function (PHP 7.4+) — expression unique
$double = fn(int $n): int => $n * 2;

// Closure classique (accès au scope parent via use)
$facteur = 3;
$multiply = function(int $n) use ($facteur): int ;

// Arguments nommés (PHP 8+)
function createUser(string $nom, int $age, string $role = « user »): array
createUser(nom: « Alice », age: 25);
createUser(age: 30, nom: « Bob »); // L'ordre n'importe plus

// Variadic (…args)
function somme(int $nombres): int
somme(1, 2, 3); // 6

🧠 Quiz
Différence entre fn() => et function() ?
fn() (arrow function) = expression unique, capture automatiquement le scope parent. function() = multi-lignes, nécessite use ($var) pour accéder aux variables parentes.

CHAPITRE 08

POO : Classes et objets

🏛️ Définir une classe
class User

$alice = new User(« Alice », 25, 1);
echo $alice->saluer();

⚡ Constructor Promotion (PHP 8+)
// Raccourci : propriétés déclarées et assignées dans le constructeur
class User {
public function __construct(
private string $nom,
private int $age,
public readonly int $id,
)

public function getNom(): string { return $this->nom; }
}
// 3 lignes au lieu de 15 — même résultat

Constructor promotion = la meilleure feature de PHP 8 pour réduire le boilerplate. Ajoutez le modificateur d'accès devant le paramètre et PHP crée la propriété automatiquement.

🔒 Modificateurs d'accès
Modificateur Classe Enfant Extérieur
public
protected
private

CHAPITRE 09

Héritage et interfaces

🔗 extends et interfaces
class Admin extends User

// Interface
interface Serializable

class Product implements Serializable {
public function __construct(
private string $name,
private float $price,
)

public function toArray(): array {
return ['name' => $this->name, 'price' => $this->price];
}

public function toJson(): string {
return json_encode($this->toArray());
}
}

🎭 Traits, abstract, enums
// Trait = réutilisation de code (multi-héritage horizontal)
trait Timestampable

class Post

// Classe abstraite
abstract class Shape

// Enum (PHP 8.1+)
enum Status: string
$s = Status::Active;
$s->value; // « active »
$s->label(); // « Actif »

🧠 Quiz
À quoi servent les Traits en PHP ?
Les Traits permettent de réutiliser du code dans plusieurs classes sans héritage. Comme PHP n'a pas d'héritage multiple, les Traits résolvent ce problème en partageant des méthodes horizontalement.

CHAPITRE 10

Bases de données (PDO)

🔌 Connexion avec PDO
try catch (PDOException $e)
🛡️ Requêtes préparées (OBLIGATOIRE)
// ❌ JAMAIS — injection SQL possible
$pdo->query(« SELECT * FROM users WHERE id = $id »);

// ✅ TOUJOURS — requête préparée
$stmt = $pdo->prepare(« SELECT * FROM users WHERE id = :id »);
$stmt->execute([':id' => $id]);
$user = $stmt->fetch();

// INSERT
$stmt = $pdo->prepare(« INSERT INTO users (nom, email) VALUES (:nom, :email) »);
$stmt->execute([':nom' => $nom, ':email' => $email]);
$newId = $pdo->lastInsertId();

// UPDATE
$stmt = $pdo->prepare(« UPDATE users SET nom = :nom WHERE id = :id »);
$stmt->execute([':nom' => $nom, ':id' => $id]);

// DELETE
$stmt = $pdo->prepare(« DELETE FROM users WHERE id = :id »);
$stmt->execute([':id' => $id]);

// Récupérer plusieurs résultats
$users = $stmt->fetchAll();

JAMAIS de variables directement dans une requête SQL. Utilisez TOUJOURS des requêtes préparées (prepare + execute). C'est la protection n°1 contre les injections SQL.

CHAPITRE 11

Formulaires et sécurité

📝 Récupérer les données d'un formulaire
// Superglobales
$_GET['param'] // Paramètres d'URL (?param=value)
$_POST['champ'] // Données de formulaire POST
$_REQUEST // GET + POST (à éviter — ambigu)
$_FILES // Fichiers uploadés
$_SESSION // Données de session
$_COOKIE // Cookies
$_SERVER // Infos serveur

// Traitement sécurisé d'un formulaire
if ($_SERVER['REQUEST_METHOD'] === 'POST')

🛡️ Sécurité essentielle
// 1. XSS — échapper l'affichage HTML
echo htmlspecialchars($userInput, ENT_QUOTES, 'UTF-8');

// 2. SQL Injection — requêtes préparées (chapitre 10)
$stmt = $pdo->prepare(« SELECT * FROM users WHERE id = ? »);

// 3. CSRF — token dans les formulaires
session_start();
$_SESSION['csrf'] = bin2hex(random_bytes(32));
// Dans le form :

// 4. Mots de passe — TOUJOURS hasher
$hash = password_hash($password, PASSWORD_DEFAULT);
$ok = password_verify($password, $hash); // true/false

// 5. Validation
filter_var($email, FILTER_VALIDATE_EMAIL);
filter_var($url, FILTER_VALIDATE_URL);
filter_var($ip, FILTER_VALIDATE_IP);

Les 3 règles de sécurité PHP : 1. htmlspecialchars() pour tout affichage. 2. Requêtes préparées pour toute requête SQL. 3. password_hash() pour les mots de passe. Sans exception.

🔐 Sessions
session_start(); // Toujours en premier

// Stocker
$_SESSION['user_id'] = 42;
$_SESSION['role'] = 'admin';

// Lire
$userId = $_SESSION['user_id'] ?? null;

// Détruire
session_destroy();

CHAPITRE 12

PHP 8+ et bonnes pratiques

⚡ Nouveautés PHP 8.0 → 8.3
Feature Version Exemple
match 8.0 Switch strict qui retourne une valeur
Named arguments 8.0 fn(age: 25, nom: « A »)
Nullsafe ?-> 8.0 $user?->getAddress()?->city
Union types 8.0 string|int $value
Constructor promotion 8.0 public function __construct(private string $nom)
str_contains/starts_with 8.0 str_contains(« abc », « b »)
Enums 8.1 enum Status: string
readonly properties 8.1 public readonly string $nom
Fibers 8.1 Concurrence légère
readonly classes 8.2 readonly class Config
Intersection types 8.2 Iterator&Countable $col
json_validate() 8.3 Vérifie si un string est du JSON valide
#[Override] 8.3 Vérifie qu'une méthode surcharge le parent
Typed constants 8.3 const string NAME = 'App';
📁 Autoloading et Composer
// composer.json — gestionnaire de dépendances PHP

// Installer les dépendances
composer install

// Utiliser l'autoloader
require 'vendor/autoload.php';

// Namespaces
namespace App\Models;

class User

// Dans un autre fichier
use App\Models\User;
$user = new User();

✅ Bonnes pratiques

✅ À FAIRE
• Toujours === (strict)
• Type hints partout (params + retour)
Constructor promotion (PHP 8)
match au lieu de switch
PDO + prepare() pour la BDD
htmlspecialchars() pour l'affichage
password_hash() pour les mdp
• Composer + autoloading PSR-4
declare(strict_types=1) en haut de fichier

❌ À ÉVITER
== (comparaison loose)
• Variables dans les requêtes SQL
mysql_* fonctions (supprimées)
extract() et $$var
eval()
global $var
• echo directement du HTML non échappé
• Pas de tag de fermeture ?> (fichiers PHP purs)
@ pour masquer les erreurs

🔧 declare(strict_types=1)

declare(strict_types=1); // TOUJOURS en première ligne

function add(int $a, int $b): int

add(« 5 », 3); // ❌ TypeError ! (sans strict_types, ça aurait marché)

strict_types désactive la conversion automatique des types dans les appels de fonctions. C'est la première ligne à écrire dans tout fichier PHP sérieux. Utilisez-la systématiquement.

🧠 Quiz
Quelle est la protection n°1 contre les injections SQL ?
Les requêtes préparées (PDO::prepare + execute). Elles séparent le SQL des données, rendant toute injection impossible car les paramètres sont traités comme des valeurs, jamais comme du code SQL.
Que fait declare(strict_types=1) ?
Il désactive le type juggling dans les appels de fonctions. Si une fonction attend un int et reçoit une string, PHP lance un TypeError au lieu de convertir silencieusement.

Cours PHP Complet — Des bases à PHP 8.3+

Référence : PHP Manual | PHP The Right Way