---
title: POO PHP
source: https://synapx.fr/blog/poo-php/
date: 2026-06-26
category: Développement
site: SynapxLab
---

# Référence POO PHP – mots-clés et constructions

Liste aussi complète que possible pour PHP 8.x. Les exemples sont volontairement minimalistes.

## Mots-clés et constructions de classe

### `class`

Déclare une classe.

```php
class User {}
$u = new User();
```

### `interface`

Définit un contrat de méthodes publiques, sans implémentation.

```php
interface Loggable { public function log(string $m): void; }
```

### `trait`

Réutilisation d'implémentations entre classes.

```php
trait TLog { public function log($m){ echo $m; } }
class A { use TLog; }
```

### `extends`

Héritage de classe / d'interface.

```php
class Admin extends User {}
interface B extends Loggable {}
```

### `implements`

Indique qu'une classe s'engage à respecter l'interface.

```php
class FileLogger implements Loggable {
  public function log(string $m): void {}
}
```

### `abstract`

Désigne une classe ou une méthode incomplète, destinée à être spécialisée.

```php
abstract class Repo { abstract public function all(): array; }
```

### `final`

Empêche l'héritage (classe) ou la surcharge (méthode).

```php
final class UUID {}
class A { final public function id(){} }
```

### `public` / `protected` / `private`

Visibilités des membres.

```php
class C { public $a; protected $b; private $c; }
```

### `static` (membre)

Membre rattaché à la classe, sans instance.

```php
class C {
  public static int $n = 0;
  public static function v(){ return self::$n; }
}
```

### `static` (retour)

Retourne le type appelant (liaison tardive).

```php
class F { public function with(): static { return $this; } }
```

### `$this`

Instance courante.

```php
class C { function me(){ return $this; } }
```

### `self`

Référence la classe dans laquelle le code est défini.

```php
class A { public static function who(){ return __CLASS__; } }
```

### `parent`

Accède aux membres de la classe parente.

```php
class B extends A { public static function who(){ return parent::who(); } }
```

### `new`

Instancie une classe (ou une classe anonyme).

```php
$svc = new class { public function run(){} };
```

### `clone`

Duplique un objet (appelle `__clone()`).

```php
$u2 = clone $u;
```

### `instanceof`

Teste le type objet.

```php
if ($u2 instanceof User) { /* ... */ }
```

### `const` (de classe)

Constante liée à la classe.

```php
class C { public const VER = '1.0'; }
```

### `::class`

Retourne le nom qualifié de la classe sous forme de chaîne.

```php
$name = User::class; // "App\User" selon namespace
```

### `readonly` (propriété)

Propriété assignable une seule fois (8.1+).

```php
class C { public readonly int $id;
  function __construct(int $id){ $this->id = $id; }
}
```

### `readonly class`

Indique que toutes les propriétés sont `readonly` (8.2+).

```php
readonly class D { public int $id; }
```

### `use` (trait)

Importe un trait dans une classe.

```php
class L { use TLog; }
```

### `insteadof` (trait)

Résout les conflits de méthodes entre traits.

```php
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).

```php
class C{ use A { x as public xAlias; } }
```

### `enum`

Type énuméré orienté objet (8.1+).

```php
enum Status:string { case Ok='ok'; case Ko='ko'; }
```

### `__construct()`

Constructeur.

```php
class U { function __construct(public string $n) {} }
```

## Méthodes magiques

### `__destruct()`

Nettoyage à la destruction.

```php
class U { function __destruct(){ /* cleanup */ } }
```

### `__get()` / `__set()`

Permet d'accéder à des propriétés inaccessibles ou de leur affecter une valeur.

```php
function __get($n){ /* ... */ }
function __set($n,$v){ /* ... */ }
```

### `__isset()` / `__unset()`

Support de `isset()` / `unset()`.

```php
function __isset($n){ return false; }
function __unset($n){ /* ... */ }
```

### `__call()`

Appel d'une méthode d'instance inexistante.

```php
function __call($name, $args){ /* proxy */ }
```

### `__callStatic()`

Appel d'une méthode statique inexistante.

```php
public static function __callStatic($n,$a){ /* ... */ }
```

### `__toString()`

Conversion en chaîne.

```php
function __toString(){ return 'User#1'; }
```

### `__invoke()`

Rend l'objet appelable comme une fonction.

```php
function __invoke($x){ return $x + 1; }
```

### `__sleep()` / `__wakeup()`

Ancienne API de sérialisation ; privilégiez `__serialize()`.

```php
function __sleep(){ return ['id']; }
function __wakeup(){ /* ... */ }
```

### `__serialize()` / `__unserialize()`

API moderne de (dé)sérialisation.

```php
function __serialize(){ return ['id' => $this->id]; }
function __unserialize($d){ $this->id = $d['id']; }
```

### `__set_state()`

Reconstruction via `var_export()`.

```php
public static function __set_state($a){ return new self(); }
```

### `__debugInfo()`

Personnalise `var_dump()`.

```php
function __debugInfo(){ return ['id' => $this->id]; }
```

### `__clone()`

Personnalise le clonage.

```php
function __clone(){ $this->id = null; }
```

## Namespaces, types et patterns

### `namespace`

Permet d'organiser les classes.

```php
namespace App;
class User {}
```

### `use` (namespace)

Importe un nom qualifié ou définit un alias.

```php
use App\User as U;
$u = new U();
```

### Type `object`

Type générique indiquant « un objet ».

```php
function f(object $o): object { return $o; }
```

### Promotion de propriétés

Déclare la propriété, son type et sa visibilité directement dans le constructeur.

```php
class P { function __construct(public int $id) {} }
```

### Classe anonyme

Définie directement au point d'usage.

```php
$svc = new class { public function run(){} };
```

### Constantes magiques

Métadonnées utiles.

```php
__CLASS__, __METHOD__, __TRAIT__, __NAMESPACE__
```

### `(object)[]` / `stdClass`

Convertit un tableau (ou `null`) en objet : crée une instance de `stdClass`, objet générique acceptant des propriétés dynamiques.

```php
$a = (object)[]; // <=> $a = new stdClass();
$a->foo = 'bar';
```

### Opérateur nullsafe `?->`

Accède à une propriété ou une méthode uniquement si l'objet n'est pas `null`, sinon retourne `null`.

```php
$city = $user?->profile?->address?->city ?? 'N/A';
```

### `static::` (liaison statique tardive)

Se résout vers la classe **réellement** appelée, et non vers celle où le code est écrit ; utile en héritage.

```php
class A { public static function who(){ return static::class; } }
class B extends A {}
echo B::who(); // "B"
```

## Interfaces SPL et fonctionnalités

### `JsonSerializable`

Contrôle le JSON produit par `json_encode()`.

```php
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**.

```php
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.

```php
class C implements Countable { public function count(): int { return 42; } }
echo count(new C); // 42
```

### `IteratorAggregate`

Autorise `foreach` sur votre objet, avec une mise en oeuvre plus simple qu'une implémentation directe de `Iterator`.

```php
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`

Interface de type pour les objets convertibles en chaîne ; elle est satisfaite si `__toString()` existe.

```php
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 ramassage mémoire, ce qui limite les fuites.

```php
$wm = new WeakMap();
$o = new stdClass();
$wm[$o] = 'meta';
unset($o); // l'entrée disparaît automatiquement
```

### Attributs PHP `#[...]`

Ajoute des métadonnées déclaratives aux classes, propriétés ou méthodes.

```php
#[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é).

```php
#[AllowDynamicProperties]
class Legacy {}
$x = new Legacy; $x->foo = 'bar';
```

### `Closure::call()`

Lie temporairement une closure à un objet, avec accès à son `$this` privé ou protégé.

```php
$fn = function(){ return $this->secret; };
class Box { private string $secret='shh'; }
echo $fn->call(new Box()); // "shh"
```

### `ReflectionClass`

Fournit des capacités d'introspection sur les objets : méthodes, propriétés, attributs, etc.

```php
$r = new ReflectionClass(User::class);
$methods = array_map(fn($m)=>$m->getName(), $r->getMethods());
```

## Patterns d'objets

### Constructeurs nommés (pattern)

Remplace des `new` ambigus par des méthodes de création plus explicites.

```php
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)

Repose sur `readonly` et des méthodes `with*` qui retournent un **nouvel** objet.

```php
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

L'état est partagé entre toutes les instances, mais exposé via un accesseur d'instance. Cela permet d'écrire `$this->get()` tout en conservant une unique valeur globale.

```php
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 initialisée à la demande, stockée en `static` et exposée via `$this->getPDO()`.

```php
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, ce qui améliore la testabilité et l'injection. Cette approche convient si vous souhaitez éviter l'état global et faciliter les doublures de test.

```php
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]
    );
  }
}
```

## Interfaces : contrat et découplage

### Pourquoi les interfaces (contrat et découplage)

Elles définissent un **contrat** sans implémentation. Elles favorisent le *polymorphisme*, la **substitution** (remplacer une implémentation par une autre), le **découplage** (DIP/IoC) et des **tests** plus simples (mocks/fakes).

```php
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 étendre plusieurs contrats.

```php
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 simultanément.

```php
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.

```php
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` désigne l'implémentation ; `static` correspond à la liaison tardive, utile notamment pour les API fluentes.

```php
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)

Le retour peut être plus spécifique ; le paramètre peut être plus large.

```php
// 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

Permet de composer les contrats en union (`|`) ou en intersection (`&`) (PHP 8.0/8.1+).

```php
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)

Le type-hint sur l'interface favorise le découplage et facilite les tests.

```php
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.

```php
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é.

```php
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.

```php
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');
```

### Ségrégation des interfaces (ISP)

Mieux vaut plusieurs interfaces ciblées qu'une interface monolithique de type « god object ».

```php
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()`).

```php
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 ; **classe abstraite** = contrat, implémentation partielle et éventuel état. Si vous partagez du code ou de l'état, préférez l'abstraite ; sinon, l'interface reste plus adaptée.

```php
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.

```php
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'interopérabilité entre bibliothèques (logger, conteneur, cache, HTTP, événements...).

```php
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 ; la composition est ici préférable à l'héritage.

```php
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 plusieurs traitements en pipeline à partir d'un contrat commun.

```php
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 les tests de l'implémentation concrète.

```php
// 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) au moyen de `@template` et `@implements`.

```php
/** @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).

```php
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
```

## Chaînage de méthodes (Fluent)

### Fluent & constructeurs nommés typés sur interface

Des contrats plus expressifs grâce à `static` (fluent) et `self` (fabrique).

```php
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.

```php
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 en héritage, `self` fige la classe courante, et retourner une *interface* conserve davantage de souplesse.

```php
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, ce qui sécurise l'état.

```php
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.

```php
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();
```

## Introspection : fonctions `*_exists` et réflexion

### `function_exists()`

Vérifie si une fonction est définie.

```php
if (function_exists('mb_strtolower')) {
  $s = mb_strtolower($s);
}
```

### `method_exists()`

Vérifie si une méthode existe sur un objet ou une classe.

```php
if (method_exists($obj, 'run')) {
  $obj->run();
}
```

### `property_exists()`

Teste l'existence d'une propriété (même si `null`).

```php
if (property_exists($obj, 'id')) {
  echo $obj->id;
}
```

### `class_exists()`

Vérifie si une classe est déclarée (option d'autoload).

```php
if (class_exists(App\Service::class)) {
  $s = new App\Service();
}
```

### `interface_exists()`

Vérifie si une interface est déclarée (option d'autoload).

```php
if (interface_exists(Psr\Log\LoggerInterface::class)) {
  // ...
}
```

### `trait_exists()`

Vérifie si un trait est déclaré.

```php
if (trait_exists(App\TLog::class)) {
  // ...
}
```

### `enum_exists()` (8.1+)

Vérifie si un enum est déclaré.

```php
if (enum_exists(App\Status::class)) {
  $st = App\Status::Ok;
}
```

### `is_callable()`

Teste si une valeur est appelable (closure, `[$obj,'meth']`, etc.).

```php
$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é.

```php
if (is_a($obj, App\User::class)) { /* ... */ }
```

### `is_subclass_of()`

Vérifie qu'un type est une sous-classe d'un autre.

```php
if (is_subclass_of(App\Admin::class, App\User::class)) { /* ... */ }
```

### `get_class()`

Retourne le nom de la classe d'un objet.

```php
echo get_class($obj); // "App\User"
```

### `get_parent_class()`

Retourne la classe parente d'un objet/nom de classe.

```php
echo get_parent_class(App\Admin::class); // "App\User"
```

### `get_class_methods()`

Liste les méthodes d'une classe/objet.

```php
$methods = get_class_methods($obj);
```

### `get_class_vars()`

Retourne les propriétés par défaut d'une classe.

```php
$defaults = get_class_vars(App\User::class);
```

### `get_object_vars()`

Retourne les propriétés *accessibles* d'un objet dans le contexte courant.

```php
$props = get_object_vars($obj);
```

### `class_parents()`

Renvoie toutes les classes parentes (tableau associatif).

```php
$parents = class_parents($obj);
```

### `class_implements()`

Renvoie les interfaces implémentées.

```php
$ifaces = class_implements($obj);
```

### `class_uses()`

Renvoie les traits utilisés par une classe/objet.

```php
$traits = class_uses(App\Service::class);
```

### `get_declared_classes()`

Liste toutes les classes déclarées.

```php
$classes = get_declared_classes();
```

### `get_declared_interfaces()`

Liste toutes les interfaces déclarées.

```php
$ifaces = get_declared_interfaces();
```

### `get_declared_traits()`

Liste tous les traits déclarés.

```php
$traits = get_declared_traits();
```

### `get_declared_enums()` (8.1+)

Liste tous les enums déclarés.

```php
$enums = get_declared_enums();
```

### `get_defined_functions()`

Retourne les fonctions définies (internes & utilisateur).

```php
$fns = get_defined_functions();
```

## Manipuler des collections d'objets

### Parcours simple (`foreach`)

Permet d'itérer sur un tableau d'objets et d'accéder à leurs propriétés ou méthodes.

```php
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`)

Conserve uniquement les objets qui satisfont un prédicat. Pensez à `array_values()` pour réindexer le résultat.

```php
$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).

```php
$keepOddIdx = array_filter($users, fn($u,$i)=>$i%2===1, ARRAY_FILTER_USE_BOTH);
```

### Mapping (`array_map`)

Transforme un tableau d'objets, par exemple pour extraire une propriété ou produire un DTO.

```php
$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ère le premier objet correspondant, sans recourir à une double boucle.

```php
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))

Construit un tableau associatif indexé par une propriété, par exemple `id`.

```php
$byId = [];
foreach ($users as $u) { $byId[$u->id] = $u; }
$user2 = $byId[2] ?? null;
```

### Groupement (`groupBy`)

Regroupe les objets selon une propriété, par exemple l'âge.

```php
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` + `<=>`)

Trie par propriété, avec un critère secondaire en cas d'égalité.

```php
usort($users, fn($a,$b) => ($a->age <=> $b->age) ?: strcasecmp($a->name,$b->name));
```

### Réduction (somme/moyenne)

Agréger des valeurs dérivées des objets.

```php
$totalAge = array_reduce($users, fn($acc,$u)=>$acc+$u->age, 0);
$avgAge   = count($users) ? $totalAge / count($users) : 0;
```

### Unicité par propriété

Déduplique à partir d'une clé dérivée, par exemple `email`.

```php
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épare les objets en deux groupes selon un prédicat, par exemple actifs et inactifs.

```php
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ère une page d'objets à partir d'un couple offset/limit.

```php
$page = 2; $per = 20; $offset = ($page-1)*$per;
$items = array_slice($users, $offset, $per);
```

### Découpage fixe (`array_chunk`)

Découpe les données en lots de taille N pour un traitement par batch.

```php
foreach (array_chunk($users, 100) as $batch) {
  // traiter 100 objets à la fois
}
```

### Transformations paresseuses (générateurs)

Permet des itérations *lazy* sur de gros volumes, sans tout charger en mémoire.

```php
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`

Gère une unicité fondée sur l'identité de l'objet, et non sur une propriété, avec des métadonnées associées.

```php
$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()`.

```php
$ids = array_map(fn($u)=>$u->id, $users);
```

### Clonage en masse

Duplique des objets de manière superficielle ; prévoyez `__clone()` si une copie profonde est nécessaire.

```php
$copies = array_map(fn($u)=>clone $u, $users);
```

### Sérialisation JSON

Encode un tableau d'objets ; implémentez `JsonSerializable` pour maîtriser la sortie.

```php
echo json_encode($users, JSON_THROW_ON_ERROR); // appelle jsonSerialize() si dispo
```

### Nettoyage des vides

Élimine `null` et `false` tout en conservant les `0` valides ; précisez un callback adapté.

```php
$clean = array_values(array_filter($users, fn($u)=>$u !== null));
```
