Advanced PHP for experienced developers

Strict typing, internals, memory management, concurrency and performance: the Codara PHP bank covers what separates code that works from code that holds up in production.

Advanced typing and generics

PHP 8.4 extends typing beyond scalar types: union and intersection types, DNF types, typed properties and parameters, and generics expressed through PHPDoc. Static analysis (PHPStan, Psalm) turns these annotations into real checks at development time. A good type model makes impossible states unrepresentable and shrinks the class of errors caught too late.

/**
 * @template T
 * @param iterable<T> $items
 * @return list<T>
 */
function collect(iterable $items): array {
    return is_array($items) ? array_values($items) : iterator_to_array($items, false);
}

Memory, references and the garbage collector

PHP uses reference counting plus a cycle collector. Leaks rarely come from the engine: they come from retained references (static listeners, per-instance caches, closures capturing context). Generators make it possible to process volumes that would not fit in memory, as long as the iteration is consumed without materializing the collection.

function readLines(string $path): \Generator {
    $handle = fopen($path, 'rb');
    try {
        while (($line = fgets($handle)) !== false) {
            yield rtrim($line, "\r\n");
        }
    } finally {
        fclose($handle);
    }
}

Understanding internals to optimize

A string, an array and an object do not have the same cost: arrays are ordered hash maps with copy-on-write semantics, objects are manipulated by handle. Operations on large arrays must avoid implicit copies inside loops. Opcache compiles bytecode once and skips parsing on every request; a saturated cache costs constant recompilation.

// Avoid: $big is copied at each iteration when modified
foreach ($big as &$value) {
    $value = normalize($value);
}
unset($value); // release the residual reference

Concurrency without a framework: fibers and processes

PHP remains single-threaded, but Fibers provide cooperative suspension useful for concurrent I/O inside an event loop. For real parallelism, `pcntl_fork` and `proc_open` remain the reference tools, at the cost of explicit shared-state management. The dominant production model is still asynchronous via message queues: independent workers consume jobs without sharing memory.

$fiber = new Fiber(function (): void {
    $result = http_get('https://api.example.com/jobs');
    Fiber::suspend($result);
});

$started = $fiber->start();
// Concurrent I/O possible here
$result = $fiber->resume();