Newsgroups: php.internals Path: news.php.net Xref: news.php.net php.internals:127903 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 AD15F1A00BC for ; Sat, 5 Jul 2025 11:55:06 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=php.net; s=mail; t=1751716394; bh=WzfQswoVs2r5mifJkwsX/Y3XmTL+d5hh8/+kTIYYWKQ=; h=References:In-Reply-To:From:Date:Subject:To:Cc:From; b=Qc4+FzGzvNWQkZzKaJ08Q82I2W4WUvyZnXsnu948SRPWKjcPdfe1085eAHNVwHn8n PDQxK3zPHb5a4vF0/LVTKCBvcWpuVL89S8ZN50kvRWb1NhITL2aJH0n28LCeEIdToV sT3UJutGRs3G5V78KrUdjFr2Hl/zt+/9y9GR0H2dkIdS9j0HEr3bZCyCN8a9IZXPJI fe3ibVjAXH7L4/3v3IgCHURebHky1g27hK5OX+IVvWJlxXRZN16L2rCooga+udKCkM oAkbExMzWKTCNg9/vX9DIxw2RLSuk8M22BUfWEYYEP2rV/jVT7n79J9k6hXHmcDBl4 Yhlw98+aIFP+A== Received: from php-smtp4.php.net (localhost [127.0.0.1]) by php-smtp4.php.net (Postfix) with ESMTP id 7DD051801E6 for ; Sat, 5 Jul 2025 11:53:11 +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, 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-pj1-f42.google.com (mail-pj1-f42.google.com [209.85.216.42]) (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 ; Sat, 5 Jul 2025 11:53:06 +0000 (UTC) Received: by mail-pj1-f42.google.com with SMTP id 98e67ed59e1d1-31223a4cddeso1247376a91.1 for ; Sat, 05 Jul 2025 04:54:58 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1751716497; x=1752321297; 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=6jza50TcteIxFTkKk9hO9gF6n5iWozWdUOZ1dy8XmcM=; b=jj0dLvx3bMEieIh16TmQxiyupjwVFZm4Z6W8nE0lF4+NiRW94IFM0fd9UUIEkmFQAC ujLXDcpnUhM0l02bO/jvTATKjOYbD1j5jHU3d9dsdxzdN5qxdgQAUOB5SJCmVf8msTOI JgyxtLE8WPxDGsf7MkGqpDn2k8RbLCFkRNpa+4XSJZbnFQCqhTpl6B+8H50hTRw764Hv Tmhen3bDH8WEECgYSkj28T9FXPeSTuyorDwr1mz44RFU5diZAwMiBnl3zsqRkNBiAKc8 0WJoEqHN9Gy9OadU2JXfv+zG9jC7bqwFs59Vv+OBj6KAkhkeptXwFqbPb7muJL57bV/A qdHg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1751716497; x=1752321297; 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=6jza50TcteIxFTkKk9hO9gF6n5iWozWdUOZ1dy8XmcM=; b=QmJ0vKhhDfsoDiNH8J/6bdf/7BTGuRiNFDjt52+RSwwHN7WEgTwEc+RPZtdzu0KloP q7gF7aTmClaGVbArNPx8eBUybKSFSi79P2If0n3+t3cmeixye0LBzvX4Nbf/zYsQabcL 6nWj3Kl6FeTGcP73gfLPAg4VDMDUjte6dqzalAszS843iNZIXfifThTl/fSjJDtgRDxT aou6zu0YQMC9AVU9D/We4vJZcnLKfRmRCRhhdH9USHAL184j1i8mL0m4IzK6Jk6bsbqI 9nOgiV05wLUaeXbcX4zC/8RsVIojoz8Crc9zF7uVamB36dNbdglalO57zgjlcK30t2+I YTvQ== X-Forwarded-Encrypted: i=1; AJvYcCXqvYocBTpMtk3BLv3JYUG1wLjgpwZ2n3icZcVvbIJJqPc49b2lQFJF64PYn9Ygic1zkKWrT0JpQTA=@lists.php.net X-Gm-Message-State: AOJu0YxNtZHE+AbO/qUd4IpLkCb1FAyLqstlemxIWanE5hoYtMjrgu87 iBmPOeMp2OBNL9pFUsb3ikCWfa11gYFXWNlu+bKT8BL9R16SVLrh3MUeuzRj+H+t3iChKqqUV/l fjNVrJ5OmAv1JmBOBPgVaMVJxoZZMBPo+lUAJ X-Gm-Gg: ASbGnct31U8VypNmJeo8IaLngoWqVaue08TQlOboI23jdu+zRFNHCW4QkMf/9+Zb1FT gImiv+KtvbcqOulDt/J3r6KNx2FAc4bW1ttou96CVzZ4XK2/7j16GNKDSCPZwLFxw5m8J6MixCB OGnSAVgJ8cmNrw/nqLiCoVYpLZXI03bSkpSgculo8HBdcb X-Google-Smtp-Source: AGHT+IFmYVcnzDGAkOzsbzV99xZiXS6CYNowvNRwp0YKNAZBzariDiVoMq00BAYAIA5sSa4D4FGJMkRWRtl7bj3bUps= X-Received: by 2002:a17:90b:2ecd:b0:311:ef19:824d with SMTP id 98e67ed59e1d1-31aadcb0f0emr9545591a91.2.1751716497350; Sat, 05 Jul 2025 04:54:57 -0700 (PDT) Precedence: bulk list-help: list-post: List-Id: internals.lists.php.net x-ms-reactions: disallow MIME-Version: 1.0 References: In-Reply-To: Date: Sat, 5 Jul 2025 13:54:45 +0200 X-Gm-Features: Ac12FXyZXu-b7o_7rsoJMphFytWxUh8jcecNaS7S4rzqE9ybn0IuLB9Bw3XtmV8 Message-ID: Subject: Re: [PHP-DEV] Allowing class properties to remain Uninitialized as a default value. To: Faizan Akram Dar Cc: Bradley Hayes , Claude Pache , PHP internals Content-Type: multipart/alternative; boundary="00000000000092653306392d479b" From: cardamoneluigi@gmail.com (Luigi Cardamone) --00000000000092653306392d479b Content-Type: text/plain; charset="UTF-8" Content-Transfer-Encoding: quoted-printable On Thu, Jun 5, 2025 at 10:41=E2=80=AFAM Faizan Akram Dar wrote: > > > On Thu, 5 Jun 2025, 13:56 Bradley Hayes, wrote: > >> Here is another way to think about it, trying to make the arguments >> optional not have a new value type. >> >> Optional arguments currently requires a default value. >> >> Assigning values to properties is truly optional but we cant reflect thi= s >> in the constructor parameters. >> >> class DTO { >> public function __construct( >> public string $id, >> optional public string $name, >> optional public null|int $age, >> ) {} >> } >> new DTO('some-id'); >> new DTO(...['id' =3D> 'some-id']); // no error for missing keys for name= d arguments >> >> > > Hi Bradley, > > > You can already achieve this, just don=E2=80=99t add those properties to = the > constructor. > > Yes, static analysis tools might complain, but that=E2=80=99s fine if you= r > intention is to leave some properties uninitialized after construction. > > The constructor is, by definition, for properties that must be initialize= d > during object creation. > > > Kind regards, > Faizan > > > >> On Thu, Jun 5, 2025 at 2:33=E2=80=AFPM Bradley Hayes >> wrote: >> >>> Hey Claude, i did think of the same thing you proposed and I cover that >>> in the gihub issue I linked to. This doesnt replicate the uninitialized >>> state. >>> >>> Doing ti with custom classes or enums means now not only are forced to >>> manually check each property everywhere it might be used you also have = to >>> write thousands of checks and throw errors across all the constructors = of >>> these objects. >>> >>> When properties have an uninitialized state you remove the need to >>> handle any of this when loops and serializers simply exclude them. >>> >>> Uninitialized states is already an incredibly useful feature that exist= s >>> right now. >>> >>> Im only proposing that we have a way to tell the constructors to ignore >>> the parameter instead of being forced to have array as the only paramet= er. >>> >>> I get what you mean about null, but null is serving a different purpose= . >>> Its a value that represents nothing, so that you can assign something a= s >>> nothing. >>> >>> Uninitialized is not like assigning null to a variable. >>> >>> // This implementation: >>> class DTO { >>> public function __construct( >>> public string $id =3D uninitialized, >>> public string $name =3D uninitialized, >>> public null|int $age =3D uninitialized, >>> ) {} >>> } >>> new DTO('some-id'); >>> // Would produce the same result as this one... >>> class DTO { >>> public function __construct(array $parameters) { >>> foreach ($parameters as $key =3D> $value) { >>> $this->{$key} =3D $value; >>> } >>> } >>> } >>> new DTO(['id' =3D> 'some-id']); >>> >>> >>> On Wed, Jun 4, 2025 at 7:11=E2=80=AFPM Claude Pache >>> wrote: >>> >>>> >>>> >>>> Le 3 juin 2025 =C3=A0 06:22, Bradley Hayes a = =C3=A9crit >>>> : >>>> >>>> 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 o= n >>>> 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 =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 init= ialisation 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 f= or >>>> 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 ha= ppen >>>> 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 dat= abase >>>> in countless situations and API can assign null to delete a value from= an >>>> object. >>>> >>>> Additionally, since array unpacking now directly maps to named argumen= ts this would also save a ton of mapping code. >>>> >>>> *//array unpacking direct from the source >>>> *$dto =3D 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 ye= s 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 s= cope >>>> forcing every extender of the class to copy paste the constructor code= from >>>> the parent class. >>>> >>>> >>>> >>>> >>>> Hi Bradley, >>>> >>>> Originally, `null` was intended to mean =E2=80=9Cno value=E2=80=9D. To= day, `null` is a >>>> value in itself, and there has been a necessity to have something else= to >>>> encode an uninitialised state, meaning =E2=80=9Creally, no value=E2=80= =9D. Although I >>>> understand your specific use case, I don=E2=80=99t think that it is go= od long term >>>> design decision to rely on various built-in variations of general =E2= =80=9Cno >>>> value=E2=80=9D states: maybe tomorrow there will be a request for some= =E2=80=9Creally and >>>> truly, no value=E2=80=9D state? Instead, I think one should use >>>> application-specific states. With enums and union types, it is possibl= e: >>>> >>>> ```php >>>> enum DTO_status { >>>> case uninitialized; >>>> case deleted; >>>> } >>>> >>>> >>>> class DTO { >>>> >>>> function __construct( >>>> public int|DTO_status $id =3D DTO_status::uninitialized >>>> , public string|DTO_status $name =3D DTO_status::uninitialized >>>> , public int|null|DTO_status $age =3D DTO_status::uninitialized >>>> ) { } >>>> >>>> } >>>> ``` >>>> >>>> Or, if you want to rely on the handy error =E2=80=9Cmust not be access= ed before >>>> initialization=E2=80=9D for free, you could also write: >>>> >>>> ```php >>>> class DTO { >>>> >>>> public int $id; >>>> public string $name; >>>> public int|null $age; >>>> >>>> function __construct( >>>> int|DTO_status $id =3D DTO_status::uninitialized >>>> , string|DTO_status $name =3D DTO_status::uninitialized >>>> , int|null|DTO_status $age =3D DTO_status::uninitialized >>>> ) { >>>> foreach ([ 'id', 'name', 'age' ] as $var) { >>>> if (! ${$var} instanceof DTO_status) { >>>> $this->$var =3D ${$var}; >>>> } >>>> } >>>> >>>> } >>>> >>>> } >>>> ``` >>>> >>>> With property hooks, you can support more elaborate things such as >>>> `$foo->id =3D DTO_status::deleted`, although you cannot (and should no= t) rely >>>> on the built-in =E2=80=9Cmust not be accessed before initialization=E2= =80=9D error anymore, >>>> because you cannot (and are not supposed to) return to the uninitialis= ed >>>> state: you have to manually throw the appropriate error in the getter. >>>> >>>> =E2=80=94Claude >>>> >>>> >>>> >>>> >>>> >>>> >>>> >>> >>> -- >>> >>> Bradley Hayes / Engineer / TITHE.LY >>> >>> >>> >>> >> >> -- >> >> Bradley Hayes / Engineer / TITHE.LY >> >> >> >> Hi all! This discussion seems related to the one that I started last year: https://news-web.php.net/php.internals/123338 Maybe you can find some additional feedback in that discussion. Regards, Luigi --00000000000092653306392d479b Content-Type: text/html; charset="UTF-8" Content-Transfer-Encoding: quoted-printable


On Thu, Jun 5, = 2025 at 10:41=E2=80=AFAM Faizan Akram Dar <hello@faizanakram.me> wrote:


On Thu, 5 Jun 2025, 13:56 Bradley= Hayes, <bradley.hayes@tithe.ly> wrote:
Here is another way = to think about it, trying=C2=A0to make the arguments optional not have a ne= w value type.
Optional arguments currently requires a default value.
Assigning values to properties is truly opti= onal but we cant reflect this in the constructor parameters.
=
class DTO {
public function __construct(
public string $id= ,
optional <= /span>public string $name,
= optional public null|int $age= ,
) {}
}
new DTO('some-id');
new DTO
(...['id' =3D> &= #39;some-id']); // no error for missing keys for named = arguments


Hi Br= adley,


You can already achieve this, just don=E2=80=99t add those prope= rties to the constructor.

Yes, static analysis tools might complain, but that=E2=80=99s fine if you= r intention is to leave some properties uninitialized after construction.

The constructor is, by de= finition, for properties that must be initialized during object creation.


Kind regards,
Faizan

<= /div>


On Thu, Jun 5, 2025 at 2:33= =E2=80=AFPM Bradley Hayes <bradley.hayes@tithe.ly>= wrote:
Hey Claude, i did think of the same thing you proposed and I cover= that in the gihub issue I linked to. This doesnt replicate the uninitializ= ed state.

Doing ti with custom classes or enums means no= w not only are forced to manually check each property everywhere it might b= e used you also have=C2=A0to write=C2=A0thousands=C2=A0of checks and throw = errors across all the=C2=A0constructors of these objects.

When prope= rties have an uninitialized state you=C2=A0remove the need to handle any of= this when loops and serializers simply exclude=C2=A0them.

Uninitialized states is already=C2=A0an incredibly useful feature = that exists right now.

Im only proposing that we h= ave a way to tell the constructors to ignore the parameter instead of being= forced to have array as the only parameter.

I get w= hat you mean about null, but null is serving a different purpose. Its a val= ue that represents nothing, so that you can assign something as nothing.

Uninitialized is not like assigning null to a variab= le.

// This implement=
ation:
class DTO {
public function __const= ruct(
public string <= /span>$id =3D uninitialized,
= public string $name =3D uninitialized,
public null|int $age =3D uninitialize= d,
) {}
}
new DTO('some-id');
// Would p= roduce the same result as this one...
class DTO {
= public function __construct(array $parameters) = {
foreach ($parameters as $key =3D> $value
) {
$this->{$key} =3D $value;
}
}
}
new DTO(['id' =3D> 'some-id']);

On Wed, Jun 4, 2025 at 7:11=E2=80=AFPM Claude= Pache <claude.pache@gmail.com> wrote:


Le 3 juin 2025 =C3=A0 06:22, Bradley Hayes <bradley.hayes@tithe.ly> a =C3=A9crit :

Uninitialized properties are really useful.
Being= skipped in foreach loops and JSON encoded results and other behaviours aro= und 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 an= d read-only classes, it would be great to have=C2=A0the true ability to not= specify a value.
class DTO {
public function __construct(
pub= lic string $id =3D uninitialized,
= public string $name =3D uninitialized,
public null|int = $age =3D uninitialized,
) {}}

$dto =3D new DTO(id: 'someid'= ;, age: null);
i= f ($dto->age =3D=3D=3D null) echo "no age was given\n";
echo $dto->name, PHP_EOL; // triggers th= e standard access before initialisation error

EXAMPLE: A graphQL like API that only returns data tha= t 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 fetch= ed.
(These situations usually way more complex involving multiple= =C2=A0SQL 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 think= ing the value is null. Null is considered a real value in the database in c= ountless situations and API can assign null to delete a value from an objec= t.
Ad=
ditionally, since array unpacking now directly maps to named arguments this=
 would also save a ton of mapping code.
=
//array unpacking direct from the sour=
ce
$dto =3D new DTO( ..=
.$sqlData<=
span style=3D"color:rgb(8,8,8);font-size:9.8pt">);
=
(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.)

<= /div>
I have is a discussion on this in github here:
=

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 inheritan= ce because not all the properties can be seen from the same scope forcing e= very extender of the class to copy paste the constructor code from the pare= nt class.




Hi Brad= ley,

Originally, `null` was intended to mean =E2= =80=9Cno value=E2=80=9D. Today, `null` is a value in itself, and there has = been a necessity to have something else to encode an uninitialised state, m= eaning=C2=A0=E2=80=9Creally, no value=E2=80=9D. Although I understand your = specific use case, I don=E2=80=99t think that it is good long term design d= ecision to rely on various built-in variations of general =E2=80=9Cno value= =E2=80=9D states: maybe tomorrow there will be a request for some =E2=80=9C= really and truly, no value=E2=80=9D state? Instead, I think one should use = application-specific states. With enums and union types, it is possible:

```php
enum DTO_status {
= =C2=A0 =C2=A0 case uninitialized;
=C2=A0 =C2=A0 case deleted;
}


class DTO {
=C2= =A0 =C2=A0=C2=A0
=C2=A0 =C2=A0 function __construct(
= =C2=A0 =C2=A0 =C2=A0 =C2=A0 public int|DTO_status $id =3D DTO_status::unini= tialized
=C2=A0 =C2=A0 =C2=A0 , public string|DTO_status $name = =3D DTO_status::uninitialized
=C2=A0 =C2=A0 =C2=A0 , public int|n= ull|DTO_status $age =3D DTO_status::uninitialized
=C2=A0 =C2=A0 )= { }
=C2=A0 =C2=A0=C2=A0
}
```

=
Or, if you want to rely on the handy error =E2=80=9Cmust not be = accessed before initialization=E2=80=9D for free, you could also write:

```php
class DTO {

=C2=A0 =C2=A0 public int $id;
=C2=A0 =C2=A0 public string $= name;
=C2=A0 =C2=A0 public int|null $age;
=C2=A0 =C2=A0= =C2=A0
=C2=A0 =C2=A0 function __construct(
=C2=A0 =C2= =A0 =C2=A0 =C2=A0 int|DTO_status $id =3D DTO_status::uninitialized
=C2=A0 =C2=A0 =C2=A0 , string|DTO_status $name =3D DTO_status::uninitiali= zed
=C2=A0 =C2=A0 =C2=A0 , int|null|DTO_status $age =3D DTO_statu= s::uninitialized
=C2=A0 =C2=A0 ) {=C2=A0
=C2=A0 =C2=A0 = =C2=A0 =C2=A0 foreach ([ 'id', 'name', 'age' ] as $= var) {
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 if (! ${$var} in= stanceof DTO_status) {
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 = =C2=A0 =C2=A0 $this->$var =3D ${$var};
=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=C2=A0
=C2=A0 =C2=A0 }
=C2= =A0 =C2=A0=C2=A0
}
```

W= ith property hooks, you can support more elaborate things such as `$foo->= ;id =3D DTO_status::deleted`, although you cannot (and should not) rely on = the built-in =E2=80=9Cmust not be accessed before initialization=E2=80=9D e= rror anymore, because you cannot (and are not supposed to) return to the un= initialised state: you have to manually throw the appropriate error in the = getter.

=E2=80=94Claude

<= br>






--

Bradley Hayes / Engineer / TITHE.LY






--

Bradley Hayes= / Engineer / TITHE.LY





Hi all!
This discussion seems relate= d to the one that I started last year:=C2=A0https://news-web.php.net/php.internals/123338

--00000000000092653306392d479b--