Newsgroups: php.internals Path: news.php.net Xref: news.php.net php.internals:127549 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 944511A00BC for ; Tue, 3 Jun 2025 04:22:57 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=php.net; s=mail; t=1748924453; bh=K8ijLpvuIKFoN7rawBE1GNplt3RUmItEHjEeREbwUPY=; h=From:Date:Subject:To:From; b=P4GtuX49dBsuHSHe/vALe66oxALWJsiDX7Rg9yZJNY7lhmdAUGetlXCDckiKR01pr V9GFd3git19VPQpCl5V7goKs6q2nvIsUDhw1WFEoZIEhJHsKO8L/3KWmLGw3A9xI/I dZSYZ9Dhe8/m0LchJc+aqz7LH5dteWCNBEI8BeUJiiQTPV+B3n50dBYW2FORgbdouK LlW8aGoYn4hOOWEOczBWDtOCQxu7MNiHCJup/UANW33yqoBSQKDKbhBoN204ULINtn SPuU0HOxlHjoukG6XoFFO++yS6lnEll7ffah6U/KbEZGMDNrNT3R1KuBi5WOpHPFhr hrQHKzd6dtUWg== Received: from php-smtp4.php.net (localhost [127.0.0.1]) by php-smtp4.php.net (Postfix) with ESMTP id 4E38018005D for ; Tue, 3 Jun 2025 04:20:52 +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=1.7 required=5.0 tests=BAYES_50,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,DMARC_PASS,HEADER_FROM_DIFFERENT_DOMAINS, HTML_MESSAGE,RCVD_IN_DNSWL_NONE,RCVD_IN_MSPIKE_H3,RCVD_IN_MSPIKE_WL, SPF_HELO_NONE,SPF_PASS,T_REMOTE_IMAGE autolearn=no autolearn_force=no version=4.0.1 X-Spam-Virus: Error (Cannot connect to unix socket '/var/run/clamav/clamd.ctl': connect: Connection refused) X-Envelope-From: Received: from mail-qt1-f182.google.com (mail-qt1-f182.google.com [209.85.160.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 ; Tue, 3 Jun 2025 04:20:52 +0000 (UTC) Received: by mail-qt1-f182.google.com with SMTP id d75a77b69052e-4a44b0ed780so38837271cf.3 for ; Mon, 02 Jun 2025 21:22:56 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=tithe.ly; s=google; t=1748924575; x=1749529375; darn=lists.php.net; h=to:subject:message-id:date:from:mime-version:from:to:cc:subject :date:message-id:reply-to; bh=GnjtY3/iBE9UHsruCrN28d+58JlwOrlTBvx9kZwTHR8=; b=H0mD6H98HuK2l3M3UTwNl7Cycv0W3P6oc5eQcThHCVT/VzTttP7SGYiPP12HV69Bby OA5g9di1uJukKobIB7W6bEuQpMbNppFwqqZPhMs5W4UBY5GrU/5TZhmfZ1MmVK6Qwq9o EBg6rJJueMTBO5DopQs6AT8neWsGUNEtXyznA= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1748924575; x=1749529375; h=to:subject:message-id:date:from:mime-version:x-gm-message-state :from:to:cc:subject:date:message-id:reply-to; bh=GnjtY3/iBE9UHsruCrN28d+58JlwOrlTBvx9kZwTHR8=; b=Pdb9yOFxmw7dmBIv2tDsyYXVtrh+atbxQxC/PxjG4az4vWu/24t8ZiW61RDQCjfo8+ QJmwILJwYCYJU9hF9RBdDKhbp8houMP3MiyxbzHz3r1+7jQfjXEcbIItNDcm7bIZ0wxg qj5P5AcyNy6FeABSFioFBs/B/w24Gk0evsVRhv5SbDExMxsWTYeZ1cCXrEHtF8kcSPXH 73Uii1rII7rtaNIvTeDL/gonpXizUbg3b2GtbJLfPg4SO+vQMis0Pq6lqQDl8KYxPrW8 eA6vPdKbT4Qrc56kVPjVNoALvx7CjVparCnivqzzxfOh1YzkCMHIXTE55e8VkTbS2HzN rdZw== X-Gm-Message-State: AOJu0YzcuNz8KY31o2s01NyH9noV+Hwh7o/0ZHvtuM7eHLXLHAukYXBq iQHUwBLuhVGw4noBhsHtxLK6RDo6KWI0UymzCWDo4F60L6YF8w1Da+wIqq3Oqc1jTx1fSuAdrc3 dgWvdJzfmChcS0gRjHwHwk0JBJd/cw0wkd3MeBzvz/OgbYQBUkIiB+aN3Uw== X-Gm-Gg: ASbGncu9Io82cdFcDp3GoMMvDRsCqjnBjtywUPitm5oWCYN/6BOG9NqFiF5elMl3P8O R1tQgVq6XvSApkKfs2urlB5BG7AM2pXWrKERj3pzUQIPwOLk71RuCqptOk8sx/f9y2WFl+xXrwF lRJ9n9iE1PmE4/IW3oo4NdxV5x7Qrg3MJE7AM= X-Google-Smtp-Source: AGHT+IEBmY6mW6Zj+wLguMYOO6/oVD5kpXbDw3Sth97nIdCjhg3WYlGqzJ53fgvKNRJHZ7iGHYwdTUXUho/SY6r9SgQ= X-Received: by 2002:a05:622a:5916:b0:476:a713:f783 with SMTP id d75a77b69052e-4a4440116edmr191059971cf.47.1748924575365; Mon, 02 Jun 2025 21:22:55 -0700 (PDT) Precedence: bulk list-help: list-post: List-Id: internals.lists.php.net x-ms-reactions: disallow MIME-Version: 1.0 Date: Tue, 3 Jun 2025 14:22:19 +1000 X-Gm-Features: AX0GCFtMoFbDDPpMkSVbIi4gj342qiz1zlkKrk79KjIPmCXGFTtYYdjcJx0BiAc Message-ID: Subject: [PHP-DEV] Allowing class properties to remain Uninitialized as a default value. To: internals@lists.php.net Content-Type: multipart/alternative; boundary="0000000000000dd1e60636a33c89" From: bradley.hayes@tithe.ly (Bradley Hayes) --0000000000000dd1e60636a33c89 Content-Type: text/plain; charset="UTF-8" Uninitialized properties are really useful. Being skipped in foreach loops and JSON encoded results and other behaviours around uninitialized properties save a lot of time wasted on basic checks and uncaught logical mistakes around null values. With the introduction of named arguments and promoted constructor properties and read-only classes, it would be great to have the true ability to not specify a value. class DTO { public function __construct( public string $id = uninitialized, public string $name = uninitialized, public null|int $age = uninitialized, ) {} } $dto = new DTO(id: 'someid', age: null); if ($dto->age === null) echo "no age was given\n"; echo $dto->name, PHP_EOL; // triggers the standard access before initialisation error EXAMPLE: A graphQL like API that only returns data that was asked for, is serviced by a PHP class that only fetched the data that was asked for and thus the DTO only has assigned values if they were fetched. (These situations usually way more complex involving multiple SQL joins/filters etc and nested objects/arrays in the return DTO). The DTO object has all the possible values defined on the class for type safety and IDE indexing, but allows the uninitialized error to happen if you try to use data that was never requested. Uninitialized Errors when directly accessing a property that was not assigned is also desirable as it indicates a logical error instead of thinking the value is null. Null is considered a real value in the database in countless situations and API can assign null to delete a value from an object. Additionally, since array unpacking now directly maps to named arguments this would also save a ton of mapping code. *//array unpacking direct from the source *$dto = new DTO( ...$sqlData); (FYI: SQL is way faster at mapping thousands of values to the naming convention of the class than doing it in php so we do it in SQL. So yes we would directly array unpack an sql result here.) I have is a discussion on this in github here: https://github.com/php/php-src/issues/17771 The current workaround is to make the constructor take an array as its only parameter and looping over it assigning matching array key values to class properties and ignoring the rest. This works but breaks indexing and prevents the use of class inheritance because not all the properties can be seen from the same scope forcing every extender of the class to copy paste the constructor code from the parent class. -- Bradley Hayes / Engineer / TITHE.LY --0000000000000dd1e60636a33c89 Content-Type: text/html; charset="UTF-8" Content-Transfer-Encoding: quoted-printable
Uninitialized properties are really useful.
Being skipped in foreach loops and JSON encoded results and other beh= aviours around uninitialized properties save a lot of time wasted on basic = checks and uncaught logical mistakes around null values.

With the introduction of named arguments and promoted constructor pr= operties and read-only classes, it would be great to have=C2=A0the true abi= lity to not specify a value.
class DTO {
public function = __construct(
public s= tring $id =3D uninitialized,
= public string $name =3D uninitialized,
public null|int $age =3D uninitialized,
) {}
}
$dto =3D new DTO(id:
'someid', age:= null);
if ($dto->age =3D=3D=3D null) echo "no age was given\n";
echo $dto->name, PHP_EOL; // triggers the standard access before initialisation error=

EXAMPLE: A graphQL like API tha= t only returns data that was asked for, is serviced by a PHP class that onl= y fetched the data that was asked for and thus the DTO only has assigned va= lues if they were fetched.
(These situations usually way more com= plex involving multiple=C2=A0SQL joins/filters etc and nested objects/array= s in the return DTO).

The DTO object has all the p= ossible values defined on the class for type safety and IDE indexing, but a= llows the uninitialized error to happen if you try to use data that was nev= er requested.
Uninitialized Errors when directly accessing a= property that was not assigned is also desirable as it indicates a logical= error instead of thinking the value is null. Null is considered a real val= ue in the database in countless situations and API can assign null to delet= e a value from an object.
Additionally, since array unpacking now directly maps t=
o named arguments this would also save a ton of mapping code.=
//array unpackin=
g direct from the source
$dto =3D new DTO( ...$sqlData);<=
/pre>
(FYI: SQL is way faster at mapping thousa= nds of values to the naming convention of the class than doing it in php so= we do it in SQL. So yes we would directly array unpack an sql result here.= )

I have is a discussion on this in github here:

The current workaround is to make the constructor take an array as it= s only parameter and looping over it assigning matching array key values to= class properties and ignoring the rest.

This work= s but breaks indexing and prevents the use of class inheritance because not= all the properties can be seen from the same scope forcing every extender = of the class to copy paste the constructor code from the parent class.


<= span class=3D"gmail_signature_prefix">--

Bradley Hayes / Engineer / = TITHE.LY




--0000000000000dd1e60636a33c89--