Newsgroups: php.internals Path: news.php.net Xref: news.php.net php.internals:128996 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 C00571A00BC for ; Wed, 29 Oct 2025 14:35:54 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=php.net; s=mail; t=1761748559; bh=P2F/Bn8+nxfTvNcDXymrCQ0gq8tKBg6nIh31thYrdN4=; h=References:In-Reply-To:From:Date:Subject:To:Cc:From; b=i7pYbjE+Byif6RsgqXuGEMTa9Vf2YJ0oDobF6lyacDkt9zPCraPzVdGZCA/NIWYsW KWf+/KxQsaJbSUDWf/9kmZOhjusAJUuSrbsVbIBVBmmyxwU3N5FXbvddquth3bdR8z Y4wx7pbC3Ge47/YViO0u2xes7DGmiW4/1QhYxNCrkdCUDS1WD+MzwWHVh3Z42++yxL /eE9gsBcp4tFf+5KdSikQXCdviS+q7achcNDaPLLZdDWK6yjDTOOj0mpH7rQISapcl 9bEij3pq6GoAzBXPME88dNmSeoBwBGevKm0NuRm9P3a7gjnFB/9Z7uQsTPVNLqpRNZ ZmTLmAk+85pYA== Received: from php-smtp4.php.net (localhost [127.0.0.1]) by php-smtp4.php.net (Postfix) with ESMTP id 4B2A31801E1 for ; Wed, 29 Oct 2025 14:35:58 +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=0.6 required=5.0 tests=BAYES_50,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,DMARC_PASS,FREEMAIL_FROM, RCVD_IN_DNSWL_NONE,RCVD_IN_MSPIKE_H3,RCVD_IN_MSPIKE_WL,SPF_HELO_NONE, SPF_PASS autolearn=no autolearn_force=no version=4.0.1 X-Spam-Virus: No X-Envelope-From: Received: from mail-pl1-f174.google.com (mail-pl1-f174.google.com [209.85.214.174]) (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, 29 Oct 2025 14:35:58 +0000 (UTC) Received: by mail-pl1-f174.google.com with SMTP id d9443c01a7336-290ac2ef203so70500715ad.1 for ; Wed, 29 Oct 2025 07:35:53 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1761748552; x=1762353352; darn=lists.php.net; h=content-transfer-encoding:cc:to:subject:message-id:date:from :in-reply-to:references:mime-version:from:to:cc:subject:date :message-id:reply-to; bh=7ia4VhtwsldI9lhWKrGrThhUKND7cjxr51vU2fGkA+w=; b=gXzWkgCSfLkoyv7yj+cQ8MTtMQroPEabIbRYrkA8Z3UHtQCcacLi6jgBsR5mLgl/Xs jtJTvkiOAwFHP9jm31jKumYg53UEb33hpyu3KzAOtgbuiDp+lfiewbwGk7wH8yJf5/j4 rYmZg9gDDXe12v8apK8cOg7vi41ZY5UJCkIUgarhKs6cJfuZ2YkmHRrku/hEQSyk+k0E iELcdc5owdNChB/l/1PVlpYzW+mPtrvRkvkh5BAUVmQp0vTnvABtziH74ygL6h+ml++V rCDGzfxYyRYaqofxsup0e83sb2LVv4ySh4nrLeuw+XkMw1BVUWf59zSBfaOE08AptgZ0 YXKg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1761748552; x=1762353352; h=content-transfer-encoding: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=7ia4VhtwsldI9lhWKrGrThhUKND7cjxr51vU2fGkA+w=; b=Pr3cDlNCL355OkOsDoi6MPXCDqfs5DHsED/8OeW/231Sgyo+Fcm+D0g6ixTUmn0Wys 1UnsMD8nO3KpWQCrwNrOT1VI3dgrmG/DHaKVLovQ1CrSo5re+tJPR7IPdKuXKDRQIri/ GdpDS2Y+ctafPeezBTin/NDirfNcakuPdovDUhu9z/s534Da6yK2Tkp/mwPRHBtgFNLA X8tUFfuWOyOcpHjKk2in+/P5PtV0qHqIahAUBEg91khm6hVzm92yhkw1LVKLoD6DNUIT p8b+abzhT107gen52jAE8qLmLIAsgYlxiST5jdpJ+sAxZnqOFL6vpESzl+4LzXkzA2zK zs7w== X-Gm-Message-State: AOJu0YxdnzNIgV2AJiNYjIDqEtD0gnXZps/rlCvDEkbz+dPljcA3i9UQ TB5R97aR30js1qYNyThVt5l/51GjpQqFFeg/VxVv/ESAAo5HY9+yJJxlHWyys2BLUsMIqDFD9+a haMruUBnvJ5z58shyp34iYzrh1r3ShJc= X-Gm-Gg: ASbGnctTjCoBe1ltlYJUtVLba6Co4HRDK6B6Mds/lc/O1UwJOyKNJsWiMah2C4XHECO j9TpvcS7OHv4t9nP6nH5Y1wpRr37g/QN5hmkmII6gkwg+9PkvS5WYI+TUBK6/+h+p0JHxYbt9Om f1TnwWRD7XvMYsJjj6ds8UkMTuhubTaapXqm4WsWqjiuiu0lGszwbLl6cGdpta8w6zhuKplOVjM s6RCnax7bhMWGoW5iVDgqYfuOAoA0b9eTi//VxPgXjuoUlvry5zx2EtnQ41FiowldiZUp5f X-Google-Smtp-Source: AGHT+IHcJUl30d4h3wGDvKERA02TY86c2tyMxd5VwsS4FBhXv3ZS+1a5YK1DqL/1zI89XCYAUc+Hca+MkjU4mFv6k8I= X-Received: by 2002:a17:902:db07:b0:28d:195a:7d79 with SMTP id d9443c01a7336-294dedf4305mr37226475ad.5.1761748551737; Wed, 29 Oct 2025 07:35:51 -0700 (PDT) Precedence: list list-help: list-unsubscribe: list-post: List-Id: x-ms-reactions: disallow MIME-Version: 1.0 References: In-Reply-To: Date: Wed, 29 Oct 2025 16:35:40 +0200 X-Gm-Features: AWmQ_bkdmS0RdRGXgf2M-g1qOTkkDPvQfTuO7-jyIQQdzVeYqDDFdVpRlpLOYDg Message-ID: Subject: Re: [PHP-DEV] [RFC][Discussion] Add #[NoSerialize] attribute for excluding properties or classes from serialization To: Ilija Tovilo Cc: PHP internals Content-Type: text/plain; charset="UTF-8" Content-Transfer-Encoding: quoted-printable From: lnkvisitor.ts@gmail.com (Dmytro Kulyk) Thanks for the feedback! On Tue, Oct 28, 2025 at 17:47 Ilija Tovilo wrote: > > Hi Dmytro > > On Tue, Oct 28, 2025 at 12:00=E2=80=AFAM Dmytro Kulyk wrote: > > > > I=E2=80=99d like to open a discussion about a new proposal introducing = the > > #[NoSerialize] attribute, which allows developers to explicitly > > exclude properties =E2=80=94 or even entire classes =E2=80=94 from nati= ve PHP > > serialization. > > > > RFC: https://wiki.php.net/rfc/no_serialize_attribute > > Implementation: https://github.com/php/php-src/pull/20074 > > Thank you for your proposal. I have a few comments. > > > When applied to a class, instances will be serialized as NULL. > > I don't understand the rationale for diverging from the existing > @not-serializable behavior of internal classes, which throw when > attempted to be serialized (e.g. Random\Engine\Secure). I see there's > also a separate RFC to introduce that behavior: > https://wiki.php.net/rfc/not_serializable_attribute I don't think > there's a need for both of these attributes. To demonstrate, how would > we even decide whether an internal class like PDO should get the > #[NoSerialize] or #[NotSerializable] attribute? Informing the user of > potentially incorrect serialization is the prudent option, and if they > would like to skip the serialization of a property containing a PDO > object they can simply mark it as #[NoSerialize]. > > The RFC says: > > > This approach ensures that data structures containing such objects (for= example, arrays, collections, or parent objects) remain valid and can be s= afely unserialized without errors, while clearly indicating that the value = was intentionally omitted. > > But is replacing unserializable objects with NULL in nested arrays > really the safe choice? In these cases, I feel like a custom > serializer that consciously replaces the object is warranted. This > might also cause problems for typed properties: > > #[NoSerialize] > class PDO {} > > class Foo { > /* Will be happily serialized as NULL, but can't be restored beca= use the > * property is not nullable. */ > public PDO $connection; > } > > To summarize, I'd prefer if #[NoSerialize] on classes would cause > serialize() to throw, like we already do for @not-serializable. You=E2=80=99re absolutely right that the current internal behavior (e.g. Random\Engine\Secure, CurlHandle, etc.) throws when serialization is attempted, and that the proposed #[NotSerializable] RFC formalizes this for userland classes. The intent behind #[NoSerialize] is not to diverge from that model, but to provide a softer, complementary mechanism targeting a different use case =E2=80=94 non-critical, transient classes that can safely degrade = to NULL without breaking surrounding data structures. In this example, PDO (and other resource-backed classes) should indeed use #[NotSerializable], because serialization is semantically invalid and must throw. #[NoSerialize], on the other hand, would apply to wrappers, containers, or domain objects where serialization of the rest of the structure should continue even if one field or nested object cannot be meaningfully serialized. > > > Class-level #[NoSerialize] is inherited by child classes unless explici= tly overridden. > > Can you clarify how this would work? How can you override this > attribute by omission? > > #[NoSerialize] > class Foo {} > > /* What do I add here to remove #[NoSerialize]? */ > class Bar extends Foo {} Class-level #[NoSerialize] is transparently inherited by child classes. There=E2=80=99s currently no way to override or cancel this behavior in descendants; the attribute remains effective throughout the inheritance chain. As an alternative, #[NotSerializable] could be extended to #[NotSerializable(bool $soft =3D false)], which would provide the same behavior while keeping it in a separate, more consistent attribute =E2=80= =94 avoiding the double semantics currently implied by #[NoSerialize]. > > Out of scope: JSON (json_encode(), JsonSerializable) and var_export() r= emain unaffected. > > Any future attempt to exclude properties marked as #[NoSerialize] from > json_encode() would be backwards incompatible after this RFC has been > implemented. To avoid this BC break, json_encode() would need a > separate attribute (e.g. #[NoJsonEncode]). That sounds reasonable, but > should be spelled out in the RFC. It has been added to section 2.5 > > Invalid Targets & Compile-Time Diagnostics > > What's the rationale for warning for some, but erroring for others? Initially, the idea was to make all of these cases emit warnings, but I didn=E2=80=99t figure out how to implement that consistently within the attribute validators. At this point, I don=E2=80=99t see any practical reason to allow the attrib= ute on unsupported targets, so all such cases will be changed to compile-time errors instead of warnings. Dmytro