Reading — step 1 of 6
Learn
~2 min readFunctional Patterns
PHP 7+ supports anonymous classes — classes defined and instantiated in one expression. Useful for one-off implementations of interfaces, simple test doubles, and small inline objects.
Basic syntax
$logger = new class {
public function log(string $msg): void {
echo "[LOG] $msg\n";
}
};
$logger->log('hello');
The class has no name in the program — but a generated one for type-checking purposes.
With constructor arguments
$counter = new class(10) {
public function __construct(private int $start) {}
public function next(): int {
return $this->start++;
}
};
echo $counter->next(); // 10
echo $counter->next(); // 11
Arguments after new class are passed to the constructor.
Implementing interfaces
Commonly used to satisfy a small interface inline:
interface Greeter {
public function greet(string $name): string;
}
function useGreeter(Greeter $g, string $name): void {
echo $g->greet($name) . "\n";
}
useGreeter(new class implements Greeter {
public function greet(string $name): string {
return "Hi, $name!";
}
}, 'Ada');
Great for tests where you don't want a top-level mock class.
Extending classes
abstract class Shape {
abstract public function area(): float;
}
$square = new class(5.0) extends Shape {
public function __construct(private float $side) {}
public function area(): float {
return $this->side ** 2;
}
};
echo $square->area(); // 25
When to use them
Good fits:
- Inline test doubles
- Small adapters / decorators that only one place needs
- Implementing a method-rich interface for one specific call site
- Wrapping a single closure in object form
Bad fits:
- Anything that needs a name elsewhere — debugging shows generated names like
class@anonymous - Anything used in more than one place — extract to a regular class
- Things that need a stable serialize/unserialize identity
Common mistakes
- Using anonymous classes for things that need names — error messages show
class@anonymousand the file/line, hard to read. - Reaching for them when a closure would suffice — if you only need one method,
fn(...) => ...or a closure is lighter. - Trying to typehint the type — there's no name to use, so you typehint the interface it implements.
Discussion
Ask a question, share an insight, or help someone who’s stuck.
Sign in to post a comment or reply.
Loading…