RFC: Withdraw Deprecation of __sleep() and __wakeup(), Add Soft Deprecation in Documentation
Introduction
A recent RFC to deprecate the __sleep() and __wakeup() magic methods in favor of __serialize() and __unserialize() passed by the narrowest possible margin (18–9). During and after the vote, substantial discussion revealed that the migration path is far more complex, costly, and risky than the RFC presented. This follow-up RFC proposes to withdraw the deprecation and instead introduce a soft deprecation in the documentation.
The aim is to:
- Preserve backward compatibility and avoid unnecessary burden on users.
- Encourage use of __serialize() / __unserialize() for new code.
- Gather real-world migration data before reconsidering removal.
Background
The original deprecation RFC argued:
Having multiple serialization methods… is confusing and adds unnecessary complexity…
__serialize() / __unserialize() are a straight up improvement over __sleep() / __wakeup().
However:
- The original “New Custom Object Serialization” RFC (PHP 7.4) explicitly stated:
> “There is no particular pressing need to phase out __sleep() and __wakeup().”
- That RFC positioned the new API as *additional*, not a replacement.
- The recent vote passed with minimal examples of migration, and no performance or compatibility analysis.
Problems with the Current Deprecation
1. Migration is not drop-in, produces worse code for many users
Example:
class User { public function __construct( public readonly string $id, public readonly string $email, public readonly DateTime $createdAt ) {} public function __sleep(): array { return ['id', 'email', 'createdAt']; } public function __wakeup(): void { $this->validate(); } private function validate(): void { if (!filter_var($this->email, FILTER_VALIDATE_EMAIL)) { throw new InvalidArgumentException('Invalid email'); } } }
After migration to __serialize() / __unserialize():
public function __serialize(): array { return [ 'id' => $this->id, 'email' => $this->email, 'createdAt' => $this->createdAt, ]; } public function __unserialize(array $data): void { $this->validateData($data); $this->id = $data['id']; $this->email = $data['email']; $this->createdAt = $data['createdAt']; }
- For classes with 50+ properties, the boilerplate grows significantly.
- No benefit is gained for simple mappings.
- Performance is slightly worse and code readability suffers.
2. Complex compatibility handling for inheritance and payload formats
Example using reflection to preserve compatibility:
public function __serialize(): array { $data = []; foreach ($this->__sleep() as $key) { try { $r = new \ReflectionProperty($this, $key); if ($r->isInitialized($this)) { $data[$key] = $r->getValue($this); } } catch (\ReflectionException) { $data[$key] = $this->$key; } } return $data; }
- Hard to write correctly.
- Easy to break in subclasses.
- Slower than existing __sleep() / __wakeup().
3. No technical urgency
- __sleep() / __wakeup() are not fundamentally broken.
- They serve valid, common use cases without the overhead of the new API.
- The primary motivation is language tidiness, not a security or correctness problem.
4. Narrow vote margin suggests incomplete information
- The RFC omitted migration examples and performance considerations.
- Several voters have since stated they might have voted differently with full context.
- This supports reconsideration before implementation.
Proposal
1. Withdraw the deprecation voted in previously.
2. Introduce a soft deprecation in documentation:
- Move __sleep() / __wakeup() below __serialize() / __unserialize() on the [magic methods page](https://www.php.net/language.oop5.magic).
- Add a prominent note:
> “This mechanism is maintained for backward compatibility. New code should prefer __serialize() / __unserialize().”
Benefits
- Avoids costly and risky rewrites for large codebases.
- Reduces ecosystem churn.
- Still promotes modern best practices for newcomers.
- Allows time to develop migration helpers or engine-level compatibility layers.
Drawbacks
- Keeps multiple serialization APIs in the language longer.
- Potential delay in achieving a single unified serialization mechanism.
Vote
Yes / No — Withdraw the deprecation and replace it with a documentation-based soft deprecation.