[doc-en] master: Point Serializable at the magic methods, and fix the example (#5847)
| From: | Louis-Arnaud via GitHub | 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>