#[Override] Attribute (PHP 8.3)
debt(d1/e1/b3/t3)
Closest to 'caught instantly' (d1). The #[Override] attribute is validated at class load time by the PHP engine itself — a mismatch between the attribute and an actual parent/interface method produces a fatal error immediately, before any code runs. No external tool is needed; the runtime is the detector.
Closest to 'one-line patch or single-call swap' (e1). The quick_fix states: add #[Override] above the method, or remove/rename to match the parent. Either direction is a single-line change with no refactoring required.
Closest to 'localised tax' (b3). The attribute applies to individual OOP method declarations in web/cli contexts. Teams that adopt it consistently pay a small ongoing cost of annotating override methods, but the rest of the codebase is unaffected. The common_mistake about partial adoption (false confidence) raises it slightly above b1, but it does not spread cross-cutting complexity.
Closest to 'minor surprise' (t3). The misconception field identifies the main trap: developers may believe #[Override] changes runtime behaviour or method dispatch, when it is purely a compile-time declaration with no runtime effect. This is a single, well-bounded edge case rather than a deep behavioural contradiction, so t3 fits — slightly above t1 because the 'it does something at runtime' assumption is common for similar annotations in Java/C#.
Also Known As
TL;DR
Explanation
In PHP before 8.3, you could write a method with the same name as a parent method and it would silently override it — or silently not override it if you misspelled the name. The #[Override] attribute makes the override intent explicit. When PHP loads a class with #[Override] on a method, it verifies that the method actually exists in a parent class or interface. If it doesn't — due to a rename, typo, or removed method — PHP throws an error immediately. This catches a class of silent bugs where a 'override' method is never called because it doesn't match the parent's signature.
Watch Out
Common Misconception
Why It Matters
Common Mistakes
- Not adding #[Override] to all override methods — it only helps if you use it consistently; adding it only sometimes gives false confidence.
- Confusing #[Override] with final — final prevents further overriding; #[Override] asserts that this method overrides something.
- Using #[Override] on methods that implement interface methods — this is valid and encouraged; interface method implementations count as overrides.
- Expecting #[Override] to validate signature compatibility — it only checks name existence, not parameter types or return types. Use PHPStan or Psalm for full signature checking.
Avoid When
- When a method is new to your class and does not override any parent method or interface contract — #[Override] will cause a load-time error.
- When working with dynamic or magic method patterns (__call, __get) where the 'override' relationship is intentionally implicit and not tied to a named parent method.
- When supporting legacy code where adding #[Override] to existing methods would require immediate refactoring of parent classes that cannot yet be updated.
When To Use
- You're refactoring a parent class and renaming or removing methods — mark all child implementations with #[Override] to catch accidental breaks in inheritance chains.
- You're working in a team where method names can be typo'd or misremembered — #[Override] turns silent bugs into immediate load-time errors that static analysers and CI pipelines will catch.
- You're maintaining a large codebase with deep inheritance hierarchies and need to document intent clearly — #[Override] makes it explicit that a method is intentional, not a leftover copy-paste.
- You're using a strict code standard or IDE that supports PHP 8.3+ attributes — applying #[Override] systematically improves type safety and refactoring confidence.
Code Examples
<?php
// ❌ Typo in override — silently creates a new method, parent's validate() runs
class UserValidator extends BaseValidator
{
public function validae(mixed $data): bool // typo: validae not validate
{
return is_array($data) && isset($data['email']);
}
// BaseValidator::validate() still runs — this method is never called
}
<?php
// ✅ PHP 8.3 — #[Override] catches the typo at class load time
class UserValidator extends BaseValidator
{
#[Override]
public function validate(mixed $data): bool // PHP errors if validate() not in parent
{
return is_array($data) && isset($data['email']);
}
}
// Also works with interface methods
class JsonRenderer implements RendererInterface
{
#[Override]
public function render(array $data): string
{
return json_encode($data, JSON_THROW_ON_ERROR);
}
}