-
Type:
Question
-
Resolution: Fixed
-
Priority:
Unknown
-
Affects Version/s: None
-
Component/s: Laravel
-
None
-
Not Needed
-
None
-
None
-
None
-
None
-
None
-
None
Summary
MongoStore::unserialize() returns the raw serialized string instead of the original value when the cached value is an empty array or an empty object.
Root Cause
The unserialize() method uses str_contains($value, ';') as a heuristic to detect PHP-serialized strings:
private function unserialize($value): mixed { if (! is_string($value) || ! str_contains($value, ';')) { return $value; } return unserialize($value); }
PHP's serialization format for empty arrays and empty objects does not include a semicolon:
- serialize([]) → a:0:
- serialize(new stdClass()) → O:8:"stdClass":0:
The check therefore short-circuits and returns the raw string instead of calling unserialize().
Steps to Reproduce
$result = Cache::remember('key', 60, fn () => []); // First call (cache miss): [] // Second call (cache hit): "a:0:{}" <- bug
Expected Behavior
Both calls return [].
Affected Versions
- laravel-mongodb 5.7.0
- PHP 8.5.4
Fix
Remove the str_contains guard. Because MongoStore::serialize() stores integers and floats as native numeric values (not strings), any string coming back from MongoDB is always a PHP-serialized payload and can be passed directly to unserialize():
private function unserialize($value): mixed { if (! is_string($value)) { return $value; } return unserialize($value); }
References
- GitHub issue: #3515