PHP 5 OOP Revolution — Objects by Reference
debt(d5/e3/b3/t7)
Closest to 'specialist tool catches it' (d5). The detection_hints list Rector and PHPCS as tools. The specific code pattern — the `$obj = &new ClassName()` reference-new idiom from PHP 4, absence of visibility keywords, no interfaces — is not caught by a default linter but Rector (a specialist refactoring/upgrade tool) and PHPCS with appropriate rulesets can flag these patterns. Not instantly caught by the compiler and not silently failing in production either.
Closest to 'simple parameterised fix' (e3). The quick_fix notes that legacy PHP 4-era code should be reviewed and treated as potentially relying on copy behaviour. Fixing involves replacing the `&new` idiom and auditing object-passing assumptions — more than a single-line swap but generally contained within individual components or files rather than a codebase-wide architectural rework.
Closest to 'localised tax' (b3). The applies_to covers web, cli, and queue-worker contexts broadly, but this is fundamentally a version-history concept. Once a codebase is on PHP 5+, the burden is mostly a one-time audit of legacy code rather than a persistent ongoing tax on maintainers. The tag 'version-history' signals it's a historical inflection point, not an ongoing architectural choice.
Closest to 'serious trap' (t7). The misconception is explicit: developers assume PHP always passed objects by reference, when in fact PHP 4 copied objects on every assignment. The common_mistakes reinforce this — confusing 'passed by handle' with 'passed by reference' and not realising PHP 4 limitations explain procedural-heavy inherited codebases. This contradicts what developers expect from a language claiming OOP support, placing it solidly at t7.
Also Known As
TL;DR
Explanation
PHP 4 passed objects by value like any other variable, meaning every function call or assignment copied the entire object. PHP 5 (2004) introduced a handle-based object model: variables hold a reference to an object, not a copy. PHP 5 also added interfaces, abstract classes, public/protected/private visibility, static methods and properties, __autoload, exceptions, and type hints for objects and arrays. This was the release that made PHP viable for enterprise-scale applications and frameworks like Symfony and Zend Framework.
Common Misconception
Why It Matters
Common Mistakes
- Assuming PHP always passed objects by reference
- Confusing passed by handle with passed by reference — clone() still creates a copy
- Not realising PHP 4 OOP limitations explain the procedural-heavy codebase you just inherited
Code Examples
// PHP 4 OOP — no visibility, no type hints, pass by value:
class User {
var $name; // No visibility
function getName() { return $this->name; } // No return type
}
// PHP 5+ proper OOP:
class User {
public function __construct(
private readonly string $name,
private readonly string $email,
) {}
public function getName(): string { return $this->name; }
public function getEmail(): string { return $this->email; }
}