Some properties shouldn't be saved when you serialize() an object, such as database connections, file handles or caches. Today you leave them out by writing __sleep() or __serialize() by hand. This RFC from Dmytro Kulyk adds a #[NoSerialize] attribute so you can mark those properties instead.
How it looks
Put the attribute on a property to skip it:
class Example { public string $name; #[NoSerialize] public PDO $connection; } echo serialize($object); // O:7:"Example":1:{s:4:"name";s:4:"User";}
It works in both directions. serialize() skips the property, and unserialize() ignores it if it shows up in the data. The property keeps its default value, or stays uninitialized if it has none. The RFC says this stops an attacker's payload from filling a property the class never meant to load.
Put it on a class to forbid serializing the class entirely:
#[NoSerialize] class Connection { public PDO $pdo; } serialize(new Connection()); // Exception: Serialization of 'Connection' is not allowed
Unserializing throws too. It's the same catchable Exception PHP already throws for built-in classes like CurlHandle. Child classes inherit the attribute and can't turn it off.
The rules
- If your class defines its own
__serialize()or__sleep(), the property attribute does nothing, because your code takes priority. __unserialize()receives the raw data untouched, while__wakeup()runs after the skipped properties are filtered out.- It only affects
serialize()andunserialize(), sojson_encode()andvar_export()don't change. - You can't use it on static properties, virtual properties, interfaces or traits. Doing so causes a compile error.
PHP has 107 built-in classes marked as not serializable in their C source. The RFC moves all of them to the new attribute, so reflection shows the same information for built-in classes and your own.
The RFC also points to real projects that would benefit. Magento 2 chains __sleep() five levels deep, and Symfony has six __serialize() methods that exist only to throw an exception.
What it means for existing code
You can no longer define a class called NoSerialize in the global namespace. A GitHub search found 11 classes by that name, all inside namespaces, so none of them would break.
Where it stands
It's under discussion and targets PHP 8.6 or 9.0. The page was last updated in September 2026, and the vote hasn't started yet.