Anonymous Classes

Ma Mahalakshmi V Updated 14 Nov 2026
6 min read ·Lesson 173 of 256

What Is an Anonymous Class?

In simple terms: An anonymous class is a class without a name, defined and instantiated in a single expression. It is useful when you need a small, one-off object — for example, a fake logger in a test or a tiny adapter — and creating a separate named class file would be overkill.

Technically: Since PHP 7.0, the expression new class (...) extends ... implements ... { ... } declares a class and creates an instance of it at the same time. An anonymous class can have properties, methods, a constructor, constants, and traits; it can extend a class and implement interfaces. The object behaves like any other object, and instanceof checks against its parent class and interfaces work normally.

Syntax

$object = new class (constructorArgs) extends ParentClass implements SomeInterface {
    // properties, methods, constants, use Trait;
};

Everything after new class is optional except the class body.


A First Example

<?php
interface Logger
{
    public function log(string $message): void;
}

$logger = new class implements Logger {
    public array $messages = [];

    public function log(string $message): void
    {
        $this->messages[] = $message;
    }
};

$logger->log('User asha logged in');
$logger->log('Order 501 placed');

var_dump($logger instanceof Logger);
print_r($logger->messages);

Output

bool(true)
Array
(
    [0] => User asha logged in
    [1] => Order 501 placed
)

How It Works

  1. new class implements Logger { ... } declares an unnamed class that implements Logger and immediately creates one object of it.
  2. The object can be passed anywhere a Logger is expected.
  3. The messages property lets us inspect what was logged — a typical test double.

Constructor Arguments, Inheritance, and Traits

<?php
interface TaxRule
{
    public function apply(float $amount): float;
}

abstract class BaseRule implements TaxRule
{
    protected function round(float $value): float
    {
        return round($value, 2);
    }
}

trait Describable
{
    public function describe(): string
    {
        return static::class === self::class ? 'rule' : 'anonymous rule';
    }
}

$gst = new class (18) extends BaseRule {
    use Describable;

    public function __construct(private float $percent) {}

    public function apply(float $amount): float
    {
        return $this->round($amount * (1 + $this->percent / 100));
    }
};

echo $gst->apply(1299) . "\n";
var_dump($gst instanceof TaxRule, $gst instanceof BaseRule);

Output

1532.82
bool(true)
bool(true)
  • Arguments after new class (here 18) are passed to the anonymous class's constructor.
  • extends BaseRule lets it reuse the parent's protected round() helper and inherit the TaxRule interface.
  • Traits can be used just as in named classes.

The Name of an Anonymous Class

Anonymous classes do have an internal name, generated by PHP:

<?php
interface Logger
{
    public function log(string $message): void;
}

$logger = new class implements Logger {
    public function log(string $message): void {}
};

$plain = new class {};

echo strstr(get_class($logger), "\0", true) . "\n";
echo strstr(get_class($plain), "\0", true) . "\n";
var_dump((new ReflectionClass($logger))->isAnonymous());

Output

Logger@anonymous
class@anonymous
bool(true)
  • Since PHP 8.0, the generated name starts with the parent class or first interface name followed by @anonymous (or class@anonymous if there is neither), which makes error messages and logs more readable.
  • The full name also contains a NUL byte followed by the file path and position; strstr(..., "\0", true) cuts it off for display.
  • Do not depend on the generated name in code; use instanceof or ReflectionClass::isAnonymous().

One Class per Declaration

Each new class expression in the source code defines one class. Running the same expression several times creates several objects of the same class:

<?php
function makePoint(int $x, int $y): object
{
    return new class ($x, $y) {
        public function __construct(public int $x, public int $y) {}
    };
}

$p1 = makePoint(1, 2);
$p2 = makePoint(3, 4);

var_dump(get_class($p1) === get_class($p2));
var_dump($p1 == makePoint(1, 2));

Output

bool(true)
bool(true)

Because both come from the same declaration, the objects share a class and can be compared with ==.


Practical Example: Test Doubles Without Extra Files

Anonymous classes shine in tests, where a dependency needs a small, controllable implementation:

<?php
interface ExchangeRateProvider
{
    public function rate(string $from, string $to): float;
}

final class PriceConverter
{
    public function __construct(private ExchangeRateProvider $rates) {}

    public function toInr(float $amount, string $currency): float
    {
        if ($currency === 'INR') {
            return $amount;
        }

        return round($amount * $this->rates->rate($currency, 'INR'), 2);
    }
}

// Test: a fake provider with fixed rates and a call counter
$fakeRates = new class implements ExchangeRateProvider {
    public int $calls = 0;

    public function rate(string $from, string $to): float
    {
        $this->calls++;
        return ['USD' => 83.2, 'EUR' => 90.5][$from] ?? throw new InvalidArgumentException("No rate for $from");
    }
};

$converter = new PriceConverter($fakeRates);

echo $converter->toInr(25, 'USD') . "\n";
echo $converter->toInr(10, 'EUR') . "\n";
echo $converter->toInr(500, 'INR') . "\n";
echo "Provider calls: {$fakeRates->calls}\n";

Output

2080
905
500
Provider calls: 2

Why This Works Well

  1. The real provider would call an external API; the anonymous class returns fixed, predictable rates.
  2. The calls counter verifies that INR amounts do not trigger a rate lookup.
  3. The fake lives right next to the test that uses it, which makes the test easy to read.

Readonly Anonymous Classes (PHP 8.3+)

Like named classes, anonymous classes can be declared readonly, making all their properties readonly:

<?php
$config = new readonly class ('GoCourse', 'ta') {
    public function __construct(public string $appName, public string $language) {}
};

echo $config->appName . " ({$config->language})\n";

Output

GoCourse (ta)

When to Use Anonymous Classes

Good FitBetter as a Named Class
Test doubles for interfacesLogic reused in several places
Small adapters used in exactly one placeClasses with significant behavior
Simple event listeners or callbacks needing stateAnything that should be documented, autoloaded, or found by name
PrototypingProduction domain objects

For stateless one-off behavior, a closure is often simpler than an anonymous class. Choose an anonymous class when the code must satisfy an interface or extend a class.


Common Mistakes

Large Anonymous Classes

Effect: Hard-to-read code with logic hidden inside expressions.

Fix: Extract a named class.

Relying on the Generated Class Name

Effect: Code breaks when the file or line changes.

Fix: Use instanceof with interfaces or parent classes.

Forgetting the Semicolon

Effect: Syntax error — new class { ... } is an expression and needs a ; after the closing brace when used as a statement.

Fix: End the statement with };.

Serializing Anonymous Objects

Effect: serialize() throws an exception: anonymous classes cannot be serialized.

Fix: Use named classes for objects that are serialized, cached, or queued.


Best Practices

  • Use anonymous classes for small, local implementations of interfaces, especially in tests.
  • Keep them short; extract a named class as soon as logic grows or is reused.
  • Pass dependencies through the constructor arguments of new class (...).
  • Use closures instead when no interface or parent class is needed.
  • Never depend on generated class names.

Official reference: https://www.php.net/manual/en/language.oop5.anonymous.php

0 Comments

Reviewed before they appear

No comments yet.

PHP
PHP Tutorial Index PHP Home PHP Intro PHP Install PHP Built-in Web Server PHP Syntax PHP Tags PHP and HTML PHP Comments PHP Multiline Comments PHP Variables Variables Scope Static Variables Variable Variables PHP Echo / Print PHP printf / sprintf PHP Data Types PHP Booleans PHP NULL PHP Strings String Functions Modify Strings Concatenate Strings Slicing Strings Escape Characters String Interpolation Heredoc and Nowdoc Search in Strings Multibyte Strings PHP Floats PHP Casting PHP Type Juggling PHP Math PHP Random Numbers PHP Constants PHP Magic Constants PHP Operators Arithmetic Operators Assignment Operators Comparison Operators Increment / Decrement Operators Logical Operators Null Coalescing Operator Spaceship Operator Operator Precedence PHP If...Else...Elseif PHP If PHP If Operators PHP If...Else PHP Shorthand if PHP Nested if PHP Switch PHP Match Alternative Syntax PHP Loops While Loop Do While Loop For Loop Foreach Loop Nested Loops Break Statement Continue Statement PHP Functions User-defined Functions Function Arguments Default Argument Values Pass by Reference Named Arguments Variadic Functions Return Values Type Declarations in Functions Recursive Functions Variable Functions Anonymous Functions Closures Arrow Functions First-class Callable Syntax PHP Arrays Indexed Arrays Associative Arrays Create Arrays Access Array Items Update Array Items Add Array Items Remove Array Items Sorting Arrays Multidimensional Arrays Array Destructuring Array Spread Operator Search in Arrays Merge Arrays array_map / array_filter / array_reduce Array Functions PHP Superglobals $GLOBALS $_SERVER $_REQUEST $_POST $_GET $_FILES $_COOKIE $_SESSION \$\_ENV PHP RegEx RegEx Patterns RegEx Modifiers preg_match preg_replace preg_split PHP RegEx Functions PHP Form Handling PHP Form Validation PHP Form Required PHP Form URL/E-mail Form Input Sanitizing Escaping Output (htmlspecialchars) Checkbox, Radio and Select Inputs Sticky Forms PHP Form Complete PHP Date and Time Date Formatting DateTime Class Timezones PHP Include Include vs Require PHP File Handling PHP File Open/Read PHP File Create/Write File Delete / Rename / Copy PHP Directories PHP CSV Files PHP File Upload PHP Cookies PHP Sessions PHP Filters PHP Filters Advanced PHP Callback Functions PHP JSON PHP Exceptions Error Handling Custom Error Handler Error Logging HTTP Headers and Redirects Output Buffering Sending Email PHP cURL Consuming REST APIs PHP Generators PHP What is OOP PHP Classes/Objects The $this Keyword PHP Properties PHP Methods PHP Constructor Constructor Property Promotion PHP Destructor PHP Access Modifiers Readonly Properties PHP Inheritance Method Overriding The final Keyword PHP Class Constants PHP Abstract Classes PHP Interfaces Polymorphism PHP Traits PHP Static Methods PHP Static Properties Late Static Binding Magic Methods Object Cloning Comparing Objects Anonymous Classes PHP Enums PHP Namespaces Autoloading Classes PHP Iterables Iterators Object Serialization Strict Types Union Types Nullable Types Mixed and Never Types Nullsafe Operator PHP Attributes PHP Fibers Readonly Classes Property Hooks (PHP 8.4) Asymmetric Visibility (PHP 8.4) Reflection API SPL Data Structures MySQL Database MySQL Connect MySQL Create DB MySQL Create Table MySQL Insert Data MySQL Get Last ID MySQL Insert Multiple MySQL Prepared MySQL Select Data MySQL Where MySQL Order By MySQL Delete Data MySQL Update Data MySQL Limit Data MySQL Joins with PHP Pagination with PHP PDO Introduction PDO Connect PDO Prepared Statements PDO Fetch Modes PDO Transactions PDO Error Handling PHP XML Parsers PHP SimpleXML Parser PHP SimpleXML - Get PHP XML Expat Parser PHP DOM Parser PHP XMLReader PHP XMLWriter AJAX Intro AJAX PHP AJAX Database AJAX XML AJAX Live Search AJAX Poll AJAX with JSON Security Introduction Password Hashing SQL Injection Prevention XSS Prevention CSRF Protection Session Security Secure Cookies File Upload Security Filesystem Security Error Reporting in Production Hiding PHP Encryption with Sodium PHP Configuration (php.ini) PHP Command Line (CLI) Composer PSR-4 Autoloading Installing Extensions (PECL / PIE) Debugging PHP OPcache & Performance Garbage Collection PHP-FPM Migrating to PHP 8 Project: Contact Form with Email Project: Login & Registration System Project: CRUD App with MySQL Project: Image Upload Gallery Project: Shopping Cart with Sessions Project: Simple Blog Project: REST API with PHP
Ask about this post
AI Ask about this post

Ask questions about Anonymous Classes and get answers drawn from it.

Signed-in readers only.