[doc-en] master: Point Serializable at the magic methods, and fix the example (#5847)

From: Date: Wed, 09 Sep 2026 14:04:29 +0000
Subject: [doc-en] master: Point Serializable at the magic methods, and fix the example (#5847)
Groups: php.doc.cvs 
Request: Send a blank email to doc-cvs+get-23734@lists.php.net to get a copy of this message
Author: Louis-Arnaud (lacatoire) Committer: GitHub (web-flow) Pusher: lacatoire Date: 2026-09-09T16:04:25+02:00 Commit: https://github.com/php/doc-en/commit/72d861de4970c2dbc84c391c1a4caab4a10a91fa Raw diff: https://github.com/php/doc-en/commit/72d861de4970c2dbc84c391c1a4caab4a10a91fa.diff Point Serializable at the magic methods, and fix the example (#5847) * Point Serializable at the magic methods, and fix the example The page documented the interface as the way to customise serialisation, and its only example was the deprecated form, whose expected output carried the deprecation notice. Says instead what to use, where the boundary is (the magic methods exist as of 7.4.0 and take precedence, so the interface is only of use below that), and that the magic methods have no interface to test with instanceof. The example now shows the four-method form that works either side of 7.4.0. * Scope the precedence claim to serializing The magic methods take precedence when writing, but reading is decided by the format of the data: unserialize() routes a C: payload to Serializable::unserialize() even when __unserialize() is declared, which var_unserializer.re says in as many words ("if there is both Serializable::unserialize() and __unserialize(), then both may be used, depending on the serialization format"). That is the case this page is about, reading today what an older PHP wrote, so saying the interface methods are never called was wrong in the one scenario that matters. The comments inside the example said the same thing and are corrected with it. Implementing the interface is not only of use for old versions either: it is what makes a class an instance of Serializable, which the note just below already implied. The example is retitled to the range it actually parses on: it declares a void return type, added in PHP 7.1.0, while Serializable dates back to 5.1. Changed paths: M language/predefined/serializable.xml Diff: diff --git a/language/predefined/serializable.xml b/language/predefined/serializable.xml index 636e5b249ceb..f7bdc2222f75 100644 --- a/language/predefined/serializable.xml +++ b/language/predefined/serializable.xml @@ -33,6 +33,35 @@ As of PHP 8.1.0, a class which implements <interfacename>Serializable</interfacename> without also implementing <link linkend="object.serialize">__serialize()</link> and <link linkend="object.unserialize">__unserialize()</link> will generate a deprecation warning. </para> </warning> + + <simpara> + New code should use the + <link linkend="object.serialize">__serialize()</link> and + <link linkend="object.unserialize">__unserialize()</link> magic methods + instead, available as of PHP 7.4.0. + When a class declares both them and this interface, + <function>serialize</function> always uses + <link linkend="object.serialize">__serialize()</link> and never reaches + <methodname>Serializable::serialize</methodname>. + Unserializing is decided by the format of the data instead: a payload + written by PHP 7.4.0 or later is read by + <link linkend="object.unserialize">__unserialize()</link>, one written + before it is still read by + <methodname>Serializable::unserialize</methodname>. + Implementing <interfacename>Serializable</interfacename> therefore remains + of use for reading such older payloads, and for satisfying a + <interfacename>Serializable</interfacename> type declaration; declaring all + four methods covers every case, and avoids the deprecation notice. + </simpara> + + <note> + <simpara> + The magic methods have no interface of their own, so a class which + declares them without implementing + <interfacename>Serializable</interfacename> is not an instance of it. + <function>method_exists</function> is the way to detect them. + </simpara> + </note> </section> <section xml:id="serializable.synopsis"> @@ -52,45 +81,61 @@ <section xml:id="serializable.examples"> &reftitle.examples; <example xml:id="serializable.example.basic"> - <title>Basic usage</title> + <title>Supporting PHP 7.1.0 through 7.3.0</title> + <simpara> + The magic methods carry the serialized form, and the interface methods + delegate to them, so that a single representation serves both. + </simpara> <programlisting role="php"> <![CDATA[ <?php -class obj implements Serializable { - private $data; - public function __construct() { - $this->data = "My private data"; - } - public function serialize() { - return serialize($this->data); - } - public function unserialize($data) { - $this->data = unserialize($data); +class Task implements Serializable +{ + private $label; + + public function __construct($label) + { + $this->label = $label; } - public function getData() { - return $this->data; + + public function __serialize(): array + { + return ['label' => $this->label]; } -} -$obj = new obj; -$ser = serialize($obj); + public function __unserialize(array $data): void + { + $this->label = $data['label']; + } -var_dump($ser); + // Never called as of PHP 7.4.0 + public function serialize() + { + return serialize($this->__serialize()); + } -$newobj = unserialize($ser); + // Still called as of PHP 7.4.0, for data written before it + public function unserialize($data) + { + $this->__unserialize(unserialize($data)); + } +} -var_dump($newobj->getData()); +var_dump(serialize(new Task('deploy'))); ?> ]]> </programlisting> - &example.outputs.similar; + &example.outputs; <screen> <![CDATA[ -Deprecated: obj implements the Serializable interface, which is deprecated. Implement __serialize() and __unserialize() instead (or in addition, if support for old PHP versions is necessary) in script on line 2 -string(38) "C:3:"obj":23:{s:15:"My private data";}" -string(15) "My private data" +string(40) "O:4:"Task":1:{s:5:"label";s:6:"deploy";}" ]]> </screen> + <simpara> + Prior to PHP 7.4.0, the same code serializes through the interface + instead, and outputs + <literal>string(47) "C:4:"Task":31:{a:1:{s:5:"label";s:6:"deploy";}}"</literal>. + </simpara> </example> </section>

« previous php.doc.cvs (#23734) next »