Anonymous Classes in PHP: A Practical Guide

Updated: January 10, 2024 By: Guest Contributor Post a comment

Overview

Anonymous classes in PHP offer a streamlined approach to object-oriented programming by allowing developers to declare and instantiate classes on-the-fly. They provide a concise syntax for small, one-off objects that don’t require a formal class definition.

Introduction to Anonymous Classes

Introduced in PHP 7, anonymous classes are a powerful feature for developers. They allow the creation of classes without needing to predefine them, which is particularly useful for creating simple, one-time objects. Let’s begin with the basics:


$results = usort($array, new class {
  public function __invoke($a, $b) {
    return $a <=> $b;
  }
});

In this example, we create an anonymous class with the special __invoke method to sort an array, bypassing the need to create a named comparator class.

Anonymous Classes with Inheritance and Interfaces

Anonymous classes can also extend other classes or implement interfaces.


interface Logger {
  public function log(string $msg);
}

$messageLogger = new class extends SomeLogger implements Logger {
  public function log(string $msg) {
    echo $msg;
  }
};

$messageLogger->log("This is a message.");

The anonymous class above implements the Logger interface and extends SomeLogger class, showcasing how to use inheritance and interface implementation.

Using Anonymous Classes for Test Mock-ups

Anonymous classes are particularly useful in unit testing environments, where mock objects are required to simulate the behavior of real components.


$mockDatabase = new class extends AbstractDatabase {
  public function query($sql) {
    return true;
  }
};

// Use $mockDatabase in your unit tests

Here, an anonymous class is used to create a mock version of an abstract database class for testing purposes.

Passing Parameters to Anonymous Class Constructors

Arguments can be passed to the constructors of anonymous classes, much like with named classes.


$messagePrefix = 'Error: ';
$errorLogger = new class($messagePrefix) {
  private $prefix;

  public function __construct(string $prefix) {
    $this->prefix = $prefix;
  }

  public function log(string $msg) {
    echo $this->prefix . $msg;
  }
};

$errorLogger->log("Code 123");

By passing parameters into the constructor, we can customize the anonymous class’ behavior at instantiation time.

Scoping Rules for Anonymous Classes

Anonymous classes follow the same scoping rules as regular classes, meaning they can access variables from the parent scope if necessary.


$prefix = "Notice: ";

$notifier = new class($prefix) {
  private $prefix;
  public function __construct($parentPrefix) {
    // Captures the $prefix from the parent scope
    $this->prefix = $parentPrefix;
  }

  public function notify($message) {
    echo $this->prefix . $message;
  }
};

$notifier->notify("Event occurred.");

The example defines an anonymous class that uses the $prefix variable from the surrounding scope within its constructor.

Serializing Anonymous Classes

Serializing anonymous classes can lead to issues given their lack of a formal class definition. However, it’s possible by using a wrapper class for serialization purposes.


$wrapper = new class {
  private $obj;

  public function __construct($obj) {
    $this->obj = $obj;
  }

  public function __sleep() {
    // Handle serialization logic here
    return ['obj'];
  }

  public function __wakeup() {
    // Handle unserialization logic here
  }
};

// Serialize and unserialize
$serialized = serialize(new $wrapper(new class {
  public $property = 'value';
}));
$unserialized = unserialize($serialized);

This workaround allows the serialization of anonymous classes indirectly, albeit with additional code for managing the process.

Advanced Uses of Anonymous Classes

Anonymous classes can participate in complex patterns like Factories, Strategy, and more, often reducing the amount of boilerplate code needed to implement such patterns.


// Using an unnamed class as a strategy
$strategyContext = new class(new class implements CompressionStrategy {
  public function compress($data) {
    // Compression logic
  }
}) {
  private $strategy;

  public function __construct(CompressionStrategy $compressionStrategy) {
    $this->strategy = $compressionStrategy;
  }

  public function execute($data) {
    return $this->strategy->compress($data);
  }
};

// Usage of the strategy context
$compressedData = $strategyContext->execute($data);

Here, an anonymous class is serving as a strategy within a context object in a Strategy pattern implementation.

Conclusion

Anonymous classes in PHP are a versatile tool that can simplify code, enhance design patterns, and make for easier mock-up creation in testing scenarios. Their dynamic nature empowers a cleaner, more focused codebase where the object’s functionality is closely defined where it’s used.