| class | 
        Déclare une classe. | 
        
class User {}
$u = new User();
  | 
      
      
        | interface | 
        Contrat de méthodes publiques (sans implémentation). | 
        
interface Loggable { public function log(string $m): void; }
  | 
      
      
        | trait | 
        Réutilisation d’implémentations entre classes. | 
        
trait TLog { public function log($m){ echo $m; } }
class A { use TLog; }
  | 
      
      
        | extends | 
        Héritage de classe / d’interface. | 
        
class Admin extends User {}
interface B extends Loggable {}
  | 
      
      
        | implements | 
        Une classe s’engage à appliquer l’interface. | 
        
class FileLogger implements Loggable {
  public function log(string $m): void {}
}
  | 
      
      
        | abstract | 
        Classe/méthode incomplète à spécialiser. | 
        
abstract class Repo { abstract public function all(): array; }
  | 
      
      
        | final | 
        Empêche l’héritage (classe) ou la surcharge (méthode). | 
        
final class UUID {}
class A { final public function id(){} }
  | 
      
      
        | public / protected / private | 
        Visibilités des membres. | 
        
class C { public $a; protected $b; private $c; }
  | 
      
      
        | static (membre) | 
        Membre de classe (sans instance). | 
        
class C {
  public static int $n = 0;
  public static function v(){ return self::$n; }
}
  | 
      
      
        | static (retour) | 
        Retourne le type appelant (liaison tardive). | 
        
class F { public function with(): static { return $this; } }
  | 
      
      
        | $this | 
        Instance courante. | 
        
class C { function me(){ return $this; } }
  | 
      
      
        | self | 
        Référence la classe où le code est écrit. | 
        
class A { public static function who(){ return __CLASS__; } }
  | 
      
      
        | parent | 
        Accède aux membres de la classe parente. | 
        
class B extends A { public static function who(){ return parent::who(); } }
  | 
      
      
        | new | 
        Instancie une classe (ou une classe anonyme). | 
        
$svc = new class { public function run(){} };
  | 
      
      
        | clone | 
        Duplique un objet (appelle __clone()). | 
         | 
      
      
        | instanceof | 
        Teste le type objet. | 
        
if ($u2 instanceof User) { /* ... */ }
  | 
      
      
        | const (de classe) | 
        Constante liée à la classe. | 
        
class C { public const VER = '1.0'; }
  | 
      
      
        | ::class | 
        Nom qualifié de la classe en chaîne. | 
        
$name = User::class; // "App\User" selon namespace
  | 
      
      
        | readonly (prop.) | 
        Propriété assignable une seule fois (8.1+). | 
        
class C { public readonly int $id;
  function __construct(int $id){ $this->id = $id; }
}
  | 
      
      
        | readonly class | 
        Toutes les propriétés sont readonly (8.2+). | 
        
readonly class D { public int $id; }
  | 
      
      
        | use (trait) | 
        Importe un trait dans une classe. | 
         | 
      
      
        | insteadof (trait) | 
        Résout les conflits de méthodes entre traits. | 
        
trait A{ function x(){echo 'A';} }
trait B{ function x(){echo 'B';} }
class C{ use A,B { A::x insteadof B; } }
  | 
      
      
        | as (trait) | 
        Alias (et changement de visibilité possible). | 
        
class C{ use A { x as public xAlias; } }
  | 
      
      
        | enum | 
        Type énuméré orienté objet (8.1+). | 
        
enum Status:string { case Ok='ok'; case Ko='ko'; }
  | 
      
      
        | __construct() | 
        Constructeur. | 
        
class U { function __construct(public string $n) {} }
  | 
      
      
        | __destruct() | 
        Nettoyage à la destruction. | 
        
class U { function __destruct(){ /* cleanup */ } }
  | 
      
      
        | __get() / __set() | 
        Accède/assigne des props. inaccessibles. | 
        
function __get($n){ /* ... */ }
function __set($n,$v){ /* ... */ }
  | 
      
      
        | __isset() / __unset() | 
        Support de isset() / unset(). | 
        
function __isset($n){ return false; }
function __unset($n){ /* ... */ }
  | 
      
      
        | __call() | 
        Appel d’une méthode d’instance inexistante. | 
        
function __call($name, $args){ /* proxy */ }
  | 
      
      
        | __callStatic() | 
        Appel d’une méthode statique inexistante. | 
        
public static function __callStatic($n,$a){ /* ... */ }
  | 
      
      
        | __toString() | 
        Conversion en chaîne. | 
        
function __toString(){ return 'User#1'; }
  | 
      
      
        | __invoke() | 
        Rend l’objet appelable comme une fonction. | 
        
function __invoke($x){ return $x + 1; }
  | 
      
      
        | __sleep() / __wakeup() | 
        Ancienne API de sérialisation (préférez __serialize()). | 
        
function __sleep(){ return ['id']; }
function __wakeup(){ /* ... */ }
  | 
      
      
        | __serialize() / __unserialize() | 
        API moderne de (dé)sérialisation. | 
        
function __serialize(){ return ['id' => $this->id]; }
function __unserialize($d){ $this->id = $d['id']; }
  | 
      
      
        | __set_state() | 
        Reconstruction via var_export(). | 
        
public static function __set_state($a){ return new self(); }
  | 
      
      
        | __debugInfo() | 
        Personnalise var_dump(). | 
        
function __debugInfo(){ return ['id' => $this->id]; }
  | 
      
      
        | namespace | 
        Organisation des classes. | 
        
namespace App;
class User {}
  | 
      
      
        | use (namespace) | 
        Import d’un nom qualifié / alias. | 
        
use App\User as U;
$u = new U();
  | 
      
      
        type object | 
        Type-hint générique « un objet ». | 
        
function f(object $o): object { return $o; }
  | 
      
      
        | Promotion de propriétés | 
        Déclare + type + visibilité dans le constructeur. | 
        
class P { function __construct(public int $id) {} }
  | 
      
      
        | Classe anonyme | 
        Définie à la volée. | 
        
$svc = new class { public function run(){} };
  | 
      
      
        | __clone() | 
        Personnalise le clonage. | 
        
function __clone(){ $this->id = null; }
  | 
      
      
        | Constantes magiques | 
        Métadonnées utiles. | 
        
__CLASS__, __METHOD__, __TRAIT__, __NAMESPACE__
  | 
      
  (object)[] / stdClass | 
  Cast d’un tableau (ou null) en objet : crée une instance de stdClass (objet « sac de propriétés », props dynamiques autorisées). | 
  
$a = (object)[]; <=>  $a = new stdClass();
$a->foo = 'bar';
  | 
      
  Opérateur nullsafe ?-> | 
  Accède à une propriété/méthode uniquement si l’objet n’est pas null, sinon retourne null. | 
  
$city = $user?->profile?->address?->city ?? 'N/A';
  | 
  static:: (liaison statique tardive) | 
  Résout vers la classe **réelle** appelée (pas la classe où c’est écrit), utile pour héritage. | 
  
class A { public static function who(){ return static::class; } }
class B extends A {}
echo B::who(); // "B"
  | 
  JsonSerializable | 
  Contrôle le JSON produit par json_encode(). | 
  
class U implements JsonSerializable {
  public function __construct(private int $id) {}
  public function jsonSerialize(): mixed { return ['id' => $this->id]; }
}
echo json_encode(new U(1)); // {"id":1}
  | 
  ArrayAccess | 
  Permet d’accéder à l’objet **comme un tableau**. | 
  
class Bag implements ArrayAccess {
  private array $d = [];
  public function offsetSet($k,$v):void{ $this->d[$k]=$v; }
  public function offsetGet($k):mixed{ return $this->d[$k]??null; }
  public function offsetExists($k):bool{ return isset($this->d[$k]); }
  public function offsetUnset($k):void{ unset($this->d[$k]); }
}
$b = new Bag; $b['foo']='bar';
  | 
  Countable | 
  Autorise count($obj) sur votre objet. | 
  
class C implements Countable { public function count(): int { return 42; } }
echo count(new C); // 42
  | 
  IteratorAggregate | 
  Autorise foreach sur votre objet (plus simple qu’implémenter Iterator). | 
  
class Collection implements IteratorAggregate {
  public function __construct(private array $items){}
  public function getIterator(): Traversable { yield from $this->items; }
}
foreach (new Collection([1,2,3]) as $v) {}
  | 
  Stringable | 
  Type-interface pour « convertible en string » (implémenté si __toString() existe). | 
  
class U { public function __toString(){ return 'U#1'; } }
function f(Stringable $s){ echo (string)$s; }
f(new U());
  | 
  WeakMap / WeakReference | 
  Associe des métadonnées à des objets sans empêcher leur GC (évite les fuites). | 
  
$wm = new WeakMap();
$o = new stdClass();
$wm[$o] = 'meta';
unset($o); // l'entrée disparaît automatiquement
  | 
  Attributs PHP #[...] | 
  Métadonnées déclaratives sur classes/propriétés/méthodes. | 
  
#[Attribute] class Table { public function __construct(public string $name){} }
#[Table('users')] class User {}
  | 
  #[AllowDynamicProperties] | 
  Autorise (8.2+) les **propriétés dynamiques** sur une classe donnée (déconseillé). | 
  
#[AllowDynamicProperties]
class Legacy {}
$x = new Legacy; $x->foo = 'bar';
  | 
  Closure::call() | 
  Lie temporairement une closure à un objet (accès à son $this privé/protégé). | 
  
$fn = function(){ return $this->secret; };
class Box { private string $secret='shh'; }
echo $fn->call(new Box()); // "shh"
  | 
  ReflectionClass | 
  Introspection d’objets : méthodes, props, attributs, etc. | 
  
$r = new ReflectionClass(User::class);
$methods = array_map(fn($m)=>$m->getName(), $r->getMethods());
  | 
  | Constructeurs nommés (pattern) | 
  Remplace des new ambigus par des créateurs clairs. | 
  
final class Money {
  private function __construct(private int $cents) {}
  public static function fromCents(int $c): self { return new self($c); }
  public static function fromFloat(float $v): self { return new self((int)round($v*100)); }
}
$m = Money::fromFloat(12.34);
  | 
  | Objets immuables (pattern) | 
  Utilise readonly + méthodes with* qui retournent un **nouvel** objet. | 
  
readonly class Point { public function __construct(public int $x, public int $y){} 
  public function withX(int $x): self { return new self($x, $this->y); }
}
$p2 = (new Point(1,2))->withX(3);
  | 
  Monostate : stockage static, accès via instance ($this) | 
  État partagé entre toutes les instances, mais exposé par un getter d’instance. Permet d’écrire $this->get() tout en gardant une seule valeur globale. | 
  
class A {
  private static ?int $madonnee = null;
  public function __construct() {
    if (self::$madonnee === null) {
      self::$madonnee = 123;
    }
  }
  public function get(): int {
    return self::$madonnee; // accès via $this->get()
  }
}
  | 
  PDO partagé (static) + getter d’instance | 
  Connexion unique (lazy init) stockée en static, exposée via $this->getPDO() ; pratique pour $this->getPDO()->query($sql). | 
  
final class Database {
  private static ?PDO $pdo = null;
  public function getPDO(): PDO {
    return self::$pdo ??= new PDO(
      'mysql:host=localhost;dbname=xxx;charset=utf8mb4',
      'user','pass',
      [PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION]
    );
  }
}
// usage : $req = $this->getPDO()->query($statement);
  | 
  Version 100% instance (sans static) | 
  Chaque objet gère son propre état (plus testable / injectable). Idéal si tu veux éviter le global et faciliter les mocks. | 
  
final class Database {
  private ?PDO $pdo = null;
  public function getPDO(): PDO {
    return $this->pdo ??= new PDO(
      'mysql:host=localhost;dbname=xxx;charset=utf8mb4',
      'user','pass',
      [PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION]
    );
  }
}
  | 
  | Pourquoi les interfaces (contrat & découplage) | 
  Définissent un contrat sans implémentation : permettent le polymorphisme, la substitution (remplacer une implémentation par une autre), le découplage (DIP/IoC), et des tests faciles (mocks/fakes). | 
  
interface Logger { public function log(string $m): void; }
class FileLogger implements Logger { public function log(string $m): void {/*...*/} }
class NullLogger  implements Logger { public function log(string $m): void {/* noop */} }
function run(Logger $log){ $log->log('hello'); } // n'accepte que le contrat
run(new FileLogger());
run(new NullLogger()); // interchangeable
  | 
  Interface qui extends plusieurs interfaces | 
  Une interface peut hériter de plusieurs contrats. | 
  
interface A { public function a(): void; }
interface B { public function b(): void; }
interface C extends A, B {}            // héritage multiple d'interfaces
class X implements C {
  public function a(): void {}
  public function b(): void {}
}
  | 
  Classe qui implements plusieurs interfaces | 
  Une classe peut satisfaire plusieurs contrats à la fois. | 
  
interface CsvExport { public function toCsv(): string; }
interface JsonExport{ public function toJson(): string; }
class Report implements CsvExport, JsonExport {
  public function toCsv(): string { return "a;b"; }
  public function toJson(): string { return '{"a":"b"}'; }
}
  | 
  Constantes et méthodes static dans une interface | 
  Les interfaces peuvent définir des constantes et des signatures statiques. | 
  
interface Versioned {
  public const VER = '1.0';
  public static function build(): self; // signature statique
}
class Lib implements Versioned {
  public static function build(): self { return new self(); }
}
  | 
  Types de retour self et static en interface | 
  self = l'implémentation; static = liaison tardive (fluent). | 
  
interface Fluent {
  public function with(string $k, mixed $v): static; // fluent
  public static function make(): self;               // fabrique
}
class Bag implements Fluent {
  public static function make(): self { return new self(); }
  public function with(string $k, mixed $v): static { return $this; }
}
  | 
  | Variance (retour covariant, paramètre contravariant) | 
  Retour peut être plus spécifique; paramètre peut être plus large. | 
  
// Retour covariant
interface Factory { public function make(): Traversable; }
class ItFactory implements Factory { public function make(): Iterator { return new ArrayIterator([]); } }
// Paramètre contravariant
interface Handler { public function handle(Traversable $it): void; }
class H implements Handler { public function handle(iterable $it): void {} } // plus large
  | 
  | Types union / intersection avec interfaces | 
  Composer les contrats en union (|) ou intersection (&) (PHP 8.0/8.1+). | 
  
interface A { public function a(): void; }
interface B { public function b(): void; }
function useEither(A|B $x): void { /* ... */ }   // union
interface Both { public function set(A&B $x): void; } // intersection
  | 
  | Dépendance sur interface (DI/IoC) | 
  Type-hint sur l’interface pour découpler et faciliter le test. | 
  
interface Cache { public function get(string $k): mixed; }
class Service {
  public function __construct(private Cache $cache) {}
}
  | 
  | Interface + Trait (implémentation par défaut) | 
  On déclare le contrat dans l’interface et on fournit une implémentation réutilisable via un trait. | 
  
interface Loggable { public function log(string $m): void; }
trait DefaultLog { public function log(string $m): void { /* write */ } }
class Svc implements Loggable { use DefaultLog; }
  | 
  instanceof sur une interface | 
  Vérifie à l’exécution si un objet satisfait un contrat donné. | 
  
if ($obj instanceof Psr\Log\LoggerInterface) { $obj->info('ok'); }
  | 
  | Fabrique qui retourne une interface | 
  Masque le choix d’implémentation derrière un point d’entrée unique. | 
  
interface Transport { public function send(string $data): void; }
class HttpTransport implements Transport { public function send(string $d): void {} }
class AmqpTransport implements Transport { public function send(string $d): void {} }
final class TransportFactory {
  public static function create(string $dsn): Transport {
    return str_starts_with($dsn, 'amqp:') ? new AmqpTransport() : new HttpTransport();
  }
}
$t = TransportFactory::create($dsn); $t->send('payload');
  | 
  | Segregation des interfaces (ISP) | 
  Mieux vaut plusieurs petites interfaces ciblées qu’une grosse interface « god object ». | 
  
interface Reads  { public function read(): string; }
interface Writes { public function write(string $d): void; }
class FileIO implements Reads, Writes {
  public function read(): string {/*...*/}
  public function write(string $d): void {/*...*/}
}
  | 
  | Règles d’une interface (visibilité & contenu) | 
  Les méthodes sont implicitement publiques (pas de private/protected). Une interface ne peut pas définir de propriétés d’instance; elle peut définir des constantes et des signatures (y compris __construct()). | 
  
interface Port {
  public const VER = '1.0';
  public function open(): void;       // public implicite
  public function __construct(string $dsn); // OK (sera public)
}
  | 
  | Interface vs classe abstraite (quand choisir ?) | 
  Interface = contrat pur; abstraite = contrat + implémentation partielle + état possible. Si tu as du code commun/état → abstraite; sinon → interface. | 
  
interface Hash { public function make(string $v): string; }
abstract class BaseRepo {
  protected PDO $pdo;                   // état partagé
  public function __construct(PDO $pdo){ $this->pdo = $pdo; }
  abstract public function all(): array; // contrat
  protected function map(array $r): object {/*...*/} // implémentation partielle
}
  | 
  | Enums qui implémentent une interface | 
  Un enum peut satisfaire un contrat, idéal pour garantir un comportement sur chaque case. | 
  
interface Jsonable { public function toJson(): string; }
enum Status: string implements Jsonable {
  case Ok = 'ok'; case Ko = 'ko';
  public function toJson(): string { return json_encode($this->value); }
}
echo Status::Ok->toJson(); // "ok"
  | 
  | Standards d’interop (PSR) | 
  Les interfaces PSR facilitent l’échange entre libs (logger, container, cache, HTTP, events...). | 
  
use Psr\Log\LoggerInterface;
class Service {
  public function __construct(private LoggerInterface $log) {}
  public function run(): void { $this->log->info('ok'); }
}
  | 
  | Décorateur / Proxy basé sur interface | 
  Ajoute des comportements sans modifier l’implémentation d’origine (composition > héritage). | 
  
interface Repo { public function find(int $id): object; }
final class SqlRepo implements Repo { public function find(int $id): object {/*...*/} }
final class CachedRepo implements Repo {
  public function __construct(private Repo $inner) {}
  public function find(int $id): object { /* cache autour de $inner */ return $this->inner->find($id); }
}
  | 
  | Chaîne de responsabilité / Middleware | 
  Compose des traitements en pipeline en s’appuyant sur un contrat commun. | 
  
interface Middleware {
  public function handle(Request $r, callable $next): Response;
}
final class Auth implements Middleware {
  public function handle(Request $r, callable $next): Response { /* ... */ return $next($r); }
}
  | 
  | Tests unitaires : mocks sur interface | 
  Moquer une interface découple tes tests de l’implémentation concrète. | 
  
// PHPUnit
$logger = $this->createMock(Psr\Log\LoggerInterface::class);
$logger->expects($this->once())->method('info');
$svc = new Service($logger); $svc->run();
  | 
  | Génériques (docblocks) avec interfaces | 
  Simule des types génériques pour l’analyse statique (Psalm/PHPStan) via @template/@implements. | 
  
/** @template T */
/** @implements IteratorAggregate<T> */
interface ReadonlyList extends IteratorAggregate {}
/** @template T */
final class ArrayList implements ReadonlyList {
  /** @param list<T> $items */ public function __construct(private array $items) {}
  /** @return Traversable<T> */ public function getIterator(): Traversable { yield from $this->items; }
}
  | 
  | Intersection & union avec interfaces (rappel) | 
  Exiger plusieurs contrats à la fois (intersection) ou en accepter plusieurs (union). | 
  
interface A { public function a(): void; }
interface B { public function b(): void; }
function needsBoth(A&B $x): void { $x->a(); $x->b(); } // intersection
function useEither(A|B $x): void { /* ... */ }          // union
  | 
  | Fluent & constructeurs nommés typés sur interface | 
  Contrats plus expressifs avec static (fluent) et self (fabrique). | 
  
interface Builder {
  public static function create(): self;
  public function with(string $k, mixed $v): static;
}
  | 
  | Chaînage de méthodes (Fluent Interface) | 
  Chaque méthode retourne $this pour enchaîner plusieurs appels de façon lisible. | 
  
class Query {
  private array $where = [];
  private int $limit = 0;
  public function where(string $c): static { $this->where[] = $c; return $this; }
  public function limit(int $n): static   { $this->limit   = $n; return $this; }
  public function get(): array { /* ... */ return []; }
}
$rows = (new Query())->where('a=1')->limit(10)->get();
  | 
  Typage de retour pour le chaînage : static vs self vs interface | 
  static préserve le type réel (héritage), self fige la classe courante, retourner une interface garde la souplesse. | 
  
interface Builder { public function with(string $k, mixed $v): static; }
class Base {
  public function setA(int $a): static { return $this; } // <-- mieux pour sous-classes
}
class Child extends Base {
  public function setB(int $b): static { return $this; }
}
$o = (new Child())->setA(1)->setB(2); // OK grâce à static
  | 
  | Chaînage immuable (méthodes with*) | 
  Au lieu de modifier l’objet, chaque appel retourne une nouvelle instance (sécurise l’état). | 
  
readonly class Money {
  public function __construct(public int $cents) {}
  public function withCents(int $c): self { return new self($c); }
}
$m2 = (new Money(100))->withCents(250); // $m original inchangé
  | 
  Pattern Builder (chaînage jusqu’à build()) | 
  Accumule des options via chaînage puis produit un objet final valide. | 
  
final class HttpRequest {
  public function __construct(public string $url, public array $headers = []) {}
}
final class RequestBuilder {
  private string $url = '';
  private array $headers = [];
  public static function create(): self { return new self(); }
  public function url(string $u): static { $this->url = $u; return $this; }
  public function header(string $k, string $v): static { $this->headers[$k] = $v; return $this; }
  public function build(): HttpRequest { return new HttpRequest($this->url, $this->headers); }
}
$req = RequestBuilder::create()
  ->url('https://api.local')
  ->header('Accept','application/json')
  ->build();
  | 
  function_exists() | 
  Vérifie si une fonction est définie. | 
  
if (function_exists('mb_strtolower')) {
  $s = mb_strtolower($s);
}
  | 
  method_exists() | 
  Vérifie si une méthode existe sur un objet ou une classe. | 
  
if (method_exists($obj, 'run')) {
  $obj->run();
}
  | 
  property_exists() | 
  Teste l’existence d’une propriété (même si null). | 
  
if (property_exists($obj, 'id')) {
  echo $obj->id;
}
  | 
  class_exists() | 
  Vérifie si une classe est déclarée (option d’autoload). | 
  
if (class_exists(App\Service::class)) {
  $s = new App\Service();
}
  | 
  interface_exists() | 
  Vérifie si une interface est déclarée (option d’autoload). | 
  
if (interface_exists(Psr\Log\LoggerInterface::class)) {
  // ...
}
  | 
  trait_exists() | 
  Vérifie si un trait est déclaré. | 
  
if (trait_exists(App\TLog::class)) {
  // ...
}
  | 
  enum_exists() (8.1+) | 
  Vérifie si un enum est déclaré. | 
  
if (enum_exists(App\Status::class)) {
  $st = App\Status::Ok;
}
  | 
  is_callable() | 
  Teste si une valeur est appelable (closure, [$obj,'meth'], etc.). | 
  
$cb = [$obj, 'handle'];
if (is_callable($cb)) {
  $cb('data');
}
  | 
  is_a() | 
  Vérifie si un objet (ou nom de classe) est d’un type donné. | 
  
if (is_a($obj, App\User::class)) { /* ... */ }
  | 
  is_subclass_of() | 
  Vérifie qu’un type est une sous-classe d’un autre. | 
  
if (is_subclass_of(App\Admin::class, App\User::class)) { /* ... */ }
  | 
  get_class() | 
  Retourne le nom de la classe d’un objet. | 
  
echo get_class($obj); // "App\User"
  | 
  get_parent_class() | 
  Retourne la classe parente d’un objet/nom de classe. | 
  
echo get_parent_class(App\Admin::class); // "App\User"
  | 
  get_class_methods() | 
  Liste les méthodes d’une classe/objet. | 
  
$methods = get_class_methods($obj);
  | 
  get_class_vars() | 
  Retourne les propriétés par défaut d’une classe. | 
  
$defaults = get_class_vars(App\User::class);
  | 
  get_object_vars() | 
  Retourne les propriétés accessibles d’un objet (contexte courant). | 
  
$props = get_object_vars($obj);
  | 
  class_parents() | 
  Renvoie toutes les classes parentes (tableau associatif). | 
  
$parents = class_parents($obj);
  | 
  class_implements() | 
  Renvoie les interfaces implémentées. | 
  
$ifaces = class_implements($obj);
  | 
  class_uses() | 
  Renvoie les traits utilisés par une classe/objet. | 
  
$traits = class_uses(App\Service::class);
  | 
  get_declared_classes() | 
  Liste toutes les classes déclarées. | 
  
$classes = get_declared_classes();
  | 
  get_declared_interfaces() | 
  Liste toutes les interfaces déclarées. | 
  
$ifaces = get_declared_interfaces();
  | 
  get_declared_traits() | 
  Liste tous les traits déclarés. | 
  
$traits = get_declared_traits();
  | 
  get_declared_enums() (8.1+) | 
  Liste tous les enums déclarés. | 
  
$enums = get_declared_enums();
  | 
  get_defined_functions() | 
  Retourne les fonctions définies (internes & utilisateur). | 
  
$fns = get_defined_functions();
  | 
  Parcours simple (foreach) | 
  Itérer sur un tableau d’objets et accéder aux propriétés/méthodes. | 
  
class User{ public function __construct(public int $id, public string $name){} }
$users = [new User(1,'Ana'), new User(2,'Bob')];
foreach ($users as $u) {
  echo $u->id.' '.$u->name.PHP_EOL;
}
  | 
  Filtrage (array_filter) | 
  Garder uniquement les objets qui satisfont un prédicat. Penser à array_values() pour réindexer. | 
  
$adults = array_values(array_filter($users, fn($u) => $u->age >= 18));
  | 
  Filtrage avec clés (ARRAY_FILTER_USE_BOTH) | 
  Le callback reçoit la valeur et la clé (index). | 
  
$keepOddIdx = array_filter($users, fn($u,$i)=>$i%2===1, ARRAY_FILTER_USE_BOTH);
  | 
  Mapping (array_map) | 
  Transformer un tableau d’objets (extraction d’une propriété ou DTO). | 
  
$names = array_map(fn($u) => $u->name, $users);
$rows  = array_map(fn($u) => ['id'=>$u->id,'name'=>$u->name], $users);
  | 
  | Recherche (trouver le premier) | 
  Récupérer le premier objet correspondant (sans double boucle). | 
  
function findFirst(array $items, callable $pred): ?object {
  foreach ($items as $it) if ($pred($it)) return $it;
  return null;
}
$bob = findFirst($users, fn($u)=>$u->name==='Bob');
  | 
  | Indexation par clé (lookup O(1)) | 
  Construire un tableau associatif indexé par une propriété (ex: id). | 
  
$byId = [];
foreach ($users as $u) { $byId[$u->id] = $u; }
$user2 = $byId[2] ?? null;
  | 
  Groupement (groupBy) | 
  Regrouper les objets selon une propriété (ex: âge). | 
  
function groupBy(array $items, callable $key): array {
  $out = [];
  foreach ($items as $it) { $out[$key($it)][] = $it; }
  return $out;
}
$byAge = groupBy($users, fn($u)=>$u->age);
  | 
  Tri (usort + <=>) | 
  Ordonner par propriété (et tie-breaker secondaire). | 
  
usort($users, fn($a,$b) => ($a->age <=> $b->age) ?: strcasecmp($a->name,$b->name));
  | 
  | Réduction (somme/moyenne) | 
  Aggréger des valeurs dérivées des objets. | 
  
$totalAge = array_reduce($users, fn($acc,$u)=>$acc+$u->age, 0);
$avgAge   = count($users) ? $totalAge / count($users) : 0;
  | 
  | Unicité par propriété | 
  Dédupliquer sur une clé dérivée (ex: email). | 
  
function uniqueBy(array $items, callable $key): array {
  $seen=[]; $out=[];
  foreach ($items as $it) {
    $k=$key($it);
    if (isset($seen[$k])) continue;
    $seen[$k]=true; $out[]=$it;
  }
  return $out;
}
$unique = uniqueBy($users, fn($u)=>$u->email);
  | 
  | Partition | 
  Séparer en deux groupes selon un prédicat (ex: actifs/inactifs). | 
  
function partition(array $items, callable $pred): array {
  $yes=[]; $no=[];
  foreach ($items as $it) { ($pred($it) ? $yes : $no)[] = $it; }
  return [$yes, $no];
}
[$active,$inactive] = partition($users, fn($u)=>$u->active);
  | 
  Pagination / segment (array_slice) | 
  Récupérer une page d’objets (offset/limit). | 
  
$page = 2; $per = 20; $offset = ($page-1)*$per;
$items = array_slice($users, $offset, $per);
  | 
  Découpage fixe (array_chunk) | 
  Découper en lots de taille N (batch processing). | 
  
foreach (array_chunk($users, 100) as $batch) {
  // traiter 100 objets à la fois
}
  | 
  | Transformations paresseuses (générateurs) | 
  Itérations lazy pour gros volumes sans charger tout en mémoire. | 
  
function filter(iterable $it, callable $p): iterable { foreach ($it as $x) if ($p($x)) yield $x; }
function map(iterable $it, callable $f): iterable { foreach ($it as $x) yield $f($x); }
$names = map(filter($users, fn($u)=>$u->age>=18), fn($u)=>$u->name);
foreach ($names as $n) { /* stream */ }
  | 
  Identité objet (set/map) : SplObjectStorage | 
  Unicité basée sur l’identité (pas une propriété) + métadonnées associées. | 
  
$set = new SplObjectStorage();
foreach ($users as $u) { $set->attach($u, ['seen'=>true]); }
$exists = $set->contains($users[0]); // true
  | 
  | Extraction de colonnes (objets → tableau) | 
  array_column() ne gère pas les objets; utiliser array_map(). | 
  
$ids = array_map(fn($u)=>$u->id, $users);
  | 
  | Clonage en masse | 
  Dupliquer des objets (superficiel; prévoir __clone() pour deep copy). | 
  
$copies = array_map(fn($u)=>clone $u, $users);
  | 
  | Sérialisation JSON | 
  Encoder un tableau d’objets; implémenter JsonSerializable pour contrôler la sortie. | 
  
echo json_encode($users, JSON_THROW_ON_ERROR); // appelle jsonSerialize() si dispo
  | 
  | Nettoyage des vides | 
  Éliminer null/false en conservant les 0 valides (préciser un callback). | 
  
$clean = array_values(array_filter($users, fn($u)=>$u !== null));
  |