Newsgroups: php.internals Path: news.php.net Xref: news.php.net php.internals:128467 X-Original-To: internals@lists.php.net Delivered-To: internals@lists.php.net Received: from php-smtp4.php.net (php-smtp4.php.net [45.112.84.5]) by lists.php.net (Postfix) with ESMTPS id 3E19C1A00BC for ; Wed, 13 Aug 2025 16:36:36 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=php.net; s=mail; t=1755102898; bh=sssvF6ZCGG/OnBvC4o9iGCHt0EopFMkTYPyvlWWr7d0=; h=References:In-Reply-To:From:Date:Subject:To:Cc:From; b=iCXUZ0e+o+acIZCELPGPeJ1kQlNfksIsLXUNwZsIsYELv44q2mdFSrVUD86zgT8f9 cGswRu3ENQe3WSTTDXCnwQQdzQwC16f721w2JMn7Nej+rZ271IoV86bJ2YOTJo0qN3 1cR5VwNTCW24UoR7GA9Rshg+N1pEaa8RJ0kue26u+X6NdMJxkLSJsKJ8d7pZiILvn7 NJys52XPzWo8M72Mp3B8+a9o33c/sgWKrQC4Me3Gr8QfE4drGgt41P11CuBkpZHoW1 wIMnGHd4oO+enGegMSoF3BxevKp5nqopbBrXTrMNolUFwm1v+Mnyj9R12nfclDGeCA q2ioHWSl3hEIg== Received: from php-smtp4.php.net (localhost [127.0.0.1]) by php-smtp4.php.net (Postfix) with ESMTP id AD0C5180054 for ; Wed, 13 Aug 2025 16:34:57 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 4.0.1 (2024-03-25) on php-smtp4.php.net X-Spam-Level: X-Spam-Status: No, score=-2.1 required=5.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,DMARC_PASS,FREEMAIL_FROM, FREEMAIL_REPLY,HTML_MESSAGE,RCVD_IN_DNSWL_NONE,RCVD_IN_MSPIKE_H2, SPF_HELO_NONE,SPF_PASS autolearn=no autolearn_force=no version=4.0.1 X-Spam-Virus: No X-Envelope-From: Received: from mail-qk1-f182.google.com (mail-qk1-f182.google.com [209.85.222.182]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by php-smtp4.php.net (Postfix) with ESMTPS for ; Wed, 13 Aug 2025 16:34:57 +0000 (UTC) Received: by mail-qk1-f182.google.com with SMTP id af79cd13be357-7e7fb58425cso949540685a.1 for ; Wed, 13 Aug 2025 09:36:34 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1755102994; x=1755707794; darn=lists.php.net; h=cc:to:subject:message-id:date:from:in-reply-to:references :mime-version:from:to:cc:subject:date:message-id:reply-to; bh=1uRap+PGvaAmdnGMuM6TaK95sioa2/pQ+zdQhrpAw5M=; b=Vxe7GfPIW10gZ74tNO+axMZ0vHXPnBfJgbGFgFdAjzbCPxpBjNVa/PjsaH5LdvEfVU 1dHh2gjLJUN4A2D1fPX4aBGiJL+g8MR3aD4SRIB+emACsUdPFQLrd/Rz/IqjZ7HmvMEt DpBPURXkilBlhEoz2+fygN7VdYT1Zkbeo1kiWTdqTT50ZqcbfZ4KzefwR2QS8ELWzSTN SCoVMPTY837DA1kCXEMZt0pi1FCVr221Y5ypvl0Ws4042RH+xoN9JChSkq94ku5EKle9 12h792sXpdAHLr4giz9mmRjPZ3n3bQPmVWr1NPcuC+GJmlqkfyXKrG9w5hJ2cF3jHXE0 gC+Q== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1755102994; x=1755707794; h=cc:to:subject:message-id:date:from:in-reply-to:references :mime-version:x-gm-message-state:from:to:cc:subject:date:message-id :reply-to; bh=1uRap+PGvaAmdnGMuM6TaK95sioa2/pQ+zdQhrpAw5M=; b=fbDYvkp+smqLCEHmckO3rigAJdheBsmUAmOiJv1XSFEe4lzWIspYBq//m8dJnjvCAh b5tUvn+GjdPZIpw7MRirgpsgCwm/IV6xaZbibc5m+Xjx1jd/VMYmssEaXwXleYoC9yJd xNLXqIapB+C8tNzm1+hpkSGJdPrwuJfhSm4NQWnhMMdPtQibm9CFUHWUyMwZcCdwKmwP XAIAvQ6cKdRtVxI4+4wRmkGT/+DFYxxMCDV3Kgqi2PryxZ8NSQd8GyBc8edzQc3zeKIa b1HwGeo//PyHrhlT7rByH8Dz+6mYkP7RCDmgptQNAKzESsr0YQDWyCDBfYc7FNKu7fcl urjw== X-Forwarded-Encrypted: i=1; AJvYcCWU/aNjy09mDgBVXlkbBCuQWH3tulgyz1adnG83SngbJy27tKJYAADAn7Drc0QGKx07jl7X0PbUf4M=@lists.php.net X-Gm-Message-State: AOJu0YxufMfnoPKN3q5S1DI7GwLFrVmQgXNOkmdw/zlUZU0hYTTz24uf 8D8ABpRzX+WvLvWVRhxk7TmkCsDfXJ9i6rm2GVoasnZkSQe3tfDrG/7INL77zqbwJwFUVpF0JKA pwALdveDSDMBz1Vw+eKArMvJ0IjdD8qM= X-Gm-Gg: ASbGncvihjqUHnXshmNEFe8DfTW6HeNoo8Vibi7VTniKFZYQdz5AcxMak6uw+hkiwMA Dn9zGVQBLD+xtpxLzquHHtbHwq1QvyKNfXSCbbTNxW/zcDuoBju7SET7nRNsKl9442YFUin2kTp t1Ek3ukYohkX1Ti3IpcVdNInLMD+KuRdlt5zzMLpglOT5S4Y1xKpJdpNZ0LC+PRPusAk1Ge5ZUA 3g4pgRSeWjNAHteScos/tX2ec5/E5Zwl6zeO18LGa57zbGindbp X-Google-Smtp-Source: AGHT+IGPAWe8H8LSHwz2/9dMGkIbd+eDC54TAzYqzXD/sGv35hYknYcuvQEgVcTj+JE0WxEHXOoQT8hiBB/vciwpeis= X-Received: by 2002:ae9:f446:0:b0:7e3:2b3f:3afb with SMTP id af79cd13be357-7e865267812mr399891285a.16.1755102993969; Wed, 13 Aug 2025 09:36:33 -0700 (PDT) Precedence: list list-help: list-post: List-Id: x-ms-reactions: disallow MIME-Version: 1.0 References: In-Reply-To: Date: Wed, 13 Aug 2025 18:36:22 +0200 X-Gm-Features: Ac12FXyIcRK-EW_vtnYw3dyxVI5EhcUIRb0lGBWTmuRqm1iwMci47ZG_2qDREDM Message-ID: Subject: Re: [PHP-DEV] [RFC] [VOTE] Deprecations for PHP 8.5 To: =?UTF-8?Q?Tim_D=C3=BCsterhus?= Cc: Kamil Tekiela , "Christoph M. Becker" , "Gina P. Banyard" , PHP internals Content-Type: multipart/alternative; boundary="0000000000007ffa1c063c41c292" From: nicolas.grekas+php@gmail.com (Nicolas Grekas) --0000000000007ffa1c063c41c292 Content-Type: text/plain; charset="UTF-8" Content-Transfer-Encoding: quoted-printable Le mer. 13 ao=C3=BBt 2025 =C3=A0 17:34, Nicolas Grekas a =C3=A9crit : > > > Le mer. 13 ao=C3=BBt 2025 =C3=A0 14:33, Tim D=C3=BCsterhus a =C3=A9crit : > >> Hi >> >> On 8/13/25 13:58, Nicolas Grekas wrote: >> > I wish we had some process to revert that decision. Now is the less >> costly >> > time to do it, even if it's already late. >> >> There is always the option of =E2=80=9Dnot implementing=E2=80=9D the dec= ision. Reverting >> would mean another RFC that would also require a 2/3 majority. >> > > I'm happy to do it this way if that's the consensus. > > > >> > The discussion period failed to raise the points made by Jakub in the >> PR ( >> > https://github.com/php/php-src/pull/19435) and failed a serious impact >> > analysis IMHO. >> > This should be enough to raise a flag and allow us to reconsider. >> > I wonder if people that voted in favor of deprecating __sleep/wakeup >> would >> > still vote the same now? >> >> I already participated in the PR discussion and having slept over it, I >> think it would be helpful to consider both __sleep() and __wakeup() >> separately in this discussion of whether or not to actually follow >> through with doing the deprecation. >> >> As I've mentioned in the PR, `__sleep()` is actually broken when >> inheritance is involved and there's also a trivial way to implement >> `__serialize()` while preserving compatibility: >> >> public function __serialize() { >> return get_mangled_object_vars($this); >> } >> > > Well, the way to introduce __serialize while maintaining compatibility > with both child classes and existing payloads is to copy/paste the same > boilerplate over and over: > > public function __serialize(): array > { > $data =3D []; > foreach ($this->__sleep() as $key) { > $data[$key] =3D $this->$key; > } > return $data; > } > > And then, this has exactly the same issue regarding private properties, > without any better way since this has to call __sleep to account for chil= d > classes. > This is just moving the concern elsewhere without any benefit. > On their side, child classes that do have an issue with private propertie= s > can already implement __serialize on their side, there's nothing to fix > here: __sleep works well, and there's already an upgrade path when it's n= ot > enough. > > > >> So while this one might result in some amount of migration work, it's >> reasonably easy to do. >> >> `__wakeup()` on the other hand is not broken and migrating to >> `__unserialize()` is non-trivial. >> >> So deprecating `__sleep()` with PHP 8.5 still makes sense to me. For >> `__wakeup()` I don't have a strong opinion either way and I've also >> intentionally abstained from voting on this deprecation. >> > > implementing __unserialize to satisfy a proper upgrade path for payload > and child classes might be done this way: > > public function __unserialize(array $data): void > { > foreach ($data as $key =3D> $value) { > $this->{("\0" =3D=3D=3D $key[0] ?? '') ? substr($key, 1 + > strrpos($key, "\0")) : $key} =3D $value; > } > $this->__wakeup(); > } > > Again, this doesn't work with private properties. > > The previous code was better and safer, and contained less boilerplate. > > I made a draft PR for SYmfony here: > https://github.com/symfony/symfony/pull/61407 > I'm not sure the implementation is correct yet. > That's just to show the kind of impact this could have. > > Deprecating only sleep and not wakeup would at least fix the complexity o= f > the __unserialize replacement. > But then, this would fail the purpose of the RFC, which was to get rid of > sleep/wakeup altogether. > > This deprecation is a net loss on every aspect. > > Nicolas > Here is the result of my investigation; the kind code that everybody that cares about FC/BC for child classes and payloads will have to use (above PR is up to date): public function __serialize(): array { $data =3D []; foreach ($this->__sleep() as $key) { try { if (($r =3D new \ReflectionProperty($this, $key))->isInitialized($this)) { $data[$key] =3D $r->getValue($this); } } catch (\ReflectionException) { $data[$key] =3D $this->$key; } } return $data; } public function __unserialize(array $data): void { \Closure::bind(function ($data) { foreach ($data as $key =3D> $value) { $this->{("\0" =3D=3D=3D $key[0] ?? '') ? substr($key, 1 + strrpos($key, "\0")) : $key} =3D $value; } $this->__wakeup(); }, $this, static::class)($data); } --0000000000007ffa1c063c41c292 Content-Type: text/html; charset="UTF-8" Content-Transfer-Encoding: quoted-printable


Le=C2=A0mer. 13= ao=C3=BBt 2025 =C3=A0=C2=A017:34, Nicolas Grekas <nicolas.grekas+php@gmail.com> a =C3=A9c= rit=C2=A0:


Le=C2=A0mer. 13 ao=C3=BBt= 2025 =C3=A0=C2=A014:33, Tim D=C3=BCsterhus <tim@bastelstu.be> a =C3=A9crit=C2=A0:
=
Hi

On 8/13/25 13:58, Nicolas Grekas wrote:
> I wish we had some process to revert that decision. Now is the less co= stly
> time to do it, even if it's already late.

There is always the option of =E2=80=9Dnot implementing=E2=80=9D the decisi= on. Reverting
would mean another RFC that would also require a 2/3 majority.

I'm happy to do it this way if that's the c= onsensus.

=C2=A0
> The discussion period failed to raise the points made by Jakub in the = PR (
> https://github.com/php/php-src/pull/19435) and fai= led a serious impact
> analysis IMHO.
> This should be enough to raise a flag and allow us to reconsider.
> I wonder if people that voted in favor of deprecating __sleep/wakeup w= ould
> still vote the same now?

I already participated in the PR discussion and having slept over it, I think it would be helpful to consider both __sleep() and __wakeup()
separately in this discussion of whether or not to actually follow
through with doing the deprecation.

As I've mentioned in the PR, `__sleep()` is actually broken when
inheritance is involved and there's also a trivial way to implement `__serialize()` while preserving compatibility:

=C2=A0 =C2=A0 =C2=A0public function __serialize() {
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0return get_mangled_object_vars($this); =C2=A0 =C2=A0 =C2=A0}

Well, the way to = introduce __serialize while maintaining=C2=A0compatibility with both child = classes and existing payloads is to copy/paste the same boilerplate over an= d over:

=C2=A0 =C2=A0 public function __serialize(= ): array
=C2=A0 =C2=A0 {
=C2=A0 =C2=A0 =C2=A0 =C2=A0 $data =3D [];=C2=A0 =C2=A0 =C2=A0 =C2=A0 foreach ($this->__sleep() as $key) {
=C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 $data[$key] =3D $this->$key;
= =C2=A0 =C2=A0 =C2=A0 =C2=A0 }
=C2=A0 =C2=A0 =C2=A0 =C2=A0 return $data;<= br>=C2=A0 =C2=A0 }

And then, this has exactly the = same issue regarding private properties, without any better way since this = has to call __sleep to account for child classes.
This is just mo= ving the concern elsewhere without any benefit.
On their side, ch= ild classes that do have an issue with private properties can already imple= ment __serialize on their side, there's nothing to fix here: __sleep wo= rks well, and there's already an upgrade path when it's not enough.=

=C2=A0
So while this one might result in some amount of migration work, it's <= br> reasonably easy to do.

`__wakeup()` on the other hand is not broken and migrating to
`__unserialize()` is non-trivial.

So deprecating `__sleep()` with PHP 8.5 still makes sense to me. For
`__wakeup()` I don't have a strong opinion either way and I've also=
intentionally abstained from voting on this deprecation.

implementing __unserialize to satisfy a proper upgrade pa= th for payload and child classes might be done this way:

=C2=A0 =C2=A0 public function __unserialize(array $data): void
= =C2=A0 =C2=A0 {
=C2=A0 =C2=A0 =C2=A0 =C2=A0 foreach ($data as $key =3D&g= t; $value) {
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 $this->{("= ;\0" =3D=3D=3D $key[0] ?? '') ? substr($key, 1 + strrpos($key,= "\0")) : $key} =3D $value;
=C2=A0 =C2=A0 =C2=A0 =C2=A0 }
= =C2=A0 =C2=A0 =C2=A0 =C2=A0 $this->__wakeup();
=C2=A0 =C2=A0 }
<= div>
Again, this doesn't work with private properties.

The previous code was better and safer, and containe= d less boilerplate.

I made a draft PR for SYmfony here:=C2=A0= https://github.com/symfony/symfony/pull/61407
I'm not su= re the implementation is correct yet.
That's just to show the= kind of impact this could have.

Deprecating only = sleep and not wakeup=C2=A0would at least fix the complexity of the __unseri= alize replacement.
But then, this would fail the purpose of the R= FC, which was to get rid of sleep/wakeup altogether.

This deprecation is a net loss on every aspect.

=
Nicolas

Here i= s the result of my investigation; the kind code that everybody that cares a= bout=C2=A0 FC/BC for child classes and payloads will have to use (above PR = is up to date):

=C2=A0 =C2=A0 public function __se= rialize(): array
=C2=A0 =C2=A0 {
=C2=A0 =C2=A0 =C2=A0 =C2=A0 $data = =3D [];
=C2=A0 =C2=A0 =C2=A0 =C2=A0 foreach ($this->__sleep() as $key= ) {
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 try {
=C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 if (($r =3D new \ReflectionProperty(= $this, $key))->isInitialized($this)) {
=C2=A0 =C2=A0 =C2=A0 =C2=A0 = =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 $data[$key] =3D $r->getValue($= this);
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 }
=C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 } catch (\ReflectionException) {
= =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 $data[$key] =3D $th= is->$key;
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 }
=C2=A0 =C2= =A0 =C2=A0 =C2=A0 }
=C2=A0 =C2=A0 =C2=A0 =C2=A0 return $data;
=C2=A0 = =C2=A0 }
=C2=A0 =C2=A0 public function __unserialize(array $data): void<= br>=C2=A0 =C2=A0 {
=C2=A0 =C2=A0 =C2=A0 =C2=A0 \Closure::bind(function (= $data) {
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 foreach ($data as $ke= y =3D> $value) {
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 $this->{("\0" =3D=3D=3D $key[0] ?? '') ? substr($k= ey, 1 + strrpos($key, "\0")) : $key} =3D $value;
=C2=A0 =C2=A0= =C2=A0 =C2=A0 =C2=A0 =C2=A0 }
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0= $this->__wakeup();
=C2=A0 =C2=A0 =C2=A0 =C2=A0 }, $this, static::cla= ss)($data);
=C2=A0 =C2=A0 }
=C2=A0

<= /div> --0000000000007ffa1c063c41c292--