What's the Difference Between "final class" and "readonly class" in PHP?

final and readonly are two completely different concepts in PHP and have different implications when applied to a class.

Making a class final means that it cannot be extended/subclassed:

final class Shape {}

// Fatal error: Class Triangle cannot extend final class Shape
class Triangle extends Shape {}

In contrast, making a class readonly means that:

  • All instance properties of a class are implicitly marked as readonly, and cannot be reassigned;
  • Creation of dynamic properties is not allowed (even with the #[AllowDynamicProperties] attribute);
  • Only a readonly class can extend another readonly class;
  • readonly properties can be overridden.

For example:

// PHP 8.2+
readonly class Shape
    public function __construct(
        public string $name,
        public int $sides,
    ) {}

$shape = new Shape('triangle', 3);
echo $shape->name . ' has ' . $shape->sides . ' sides'; // "triangle has 3 sides"

If you try to assign a value to any object property after instantiation, it would throw the following error:

// PHP 8.2+
// Fatal error: Uncaught Error: Cannot modify readonly property Shape::$name
$shape->name = 'circle';

This happens because all properties are implicitly readonly when you mark the class as readonly.

You can, of course, mark as a class as both, final and readonly at the same time.

This post was published by Daniyal Hamid. Daniyal currently works as the Head of Engineering in Germany and has 20+ years of experience in software engineering, design and marketing. Please show your love and support by sharing this post.