Newsgroups: php.internals Path: news.php.net Xref: news.php.net php.internals:117451 Return-Path: Delivered-To: mailing list internals@lists.php.net Received: (qmail 39063 invoked from network); 30 Mar 2022 08:49:05 -0000 Received: from unknown (HELO php-smtp4.php.net) (45.112.84.5) by pb1.pair.com with SMTP; 30 Mar 2022 08:49:05 -0000 Received: from php-smtp4.php.net (localhost [127.0.0.1]) by php-smtp4.php.net (Postfix) with ESMTP id EE9E61804A9 for ; Wed, 30 Mar 2022 03:17:31 -0700 (PDT) X-Spam-Checker-Version: SpamAssassin 3.4.2 (2018-09-13) on php-smtp4.php.net X-Spam-Level: X-Spam-Status: No, score=-1.3 required=5.0 tests=BAYES_00,BODY_8BITS, DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,NICE_REPLY_A, RCVD_IN_DNSWL_LOW,SPF_HELO_NONE,SPF_PASS,T_SCC_BODY_TEXT_LINE autolearn=no autolearn_force=no version=3.4.2 X-Spam-ASN: AS3301 81.224.0.0/12 X-Spam-Virus: No X-Envelope-From: Received: from ts201-smtpout81.ddc.teliasonera.net (ts201-smtpout81.ddc.teliasonera.net [81.236.60.144]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange ECDHE (P-256) server-signature RSA-PSS (4096 bits) server-digest SHA256) (No client certificate requested) by php-smtp4.php.net (Postfix) with ESMTPS for ; Wed, 30 Mar 2022 03:17:31 -0700 (PDT) Received: from ts201-smtpout72.ddc.teliasonera.net (ts201-smtpout72.ddc.teliasonera.net [81.236.60.177]) by ts201-smtpout81.ddc.teliasonera.net (Postfix) with ESMTPS id DD751404142; Wed, 30 Mar 2022 12:17:28 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=telia.com; s=tssemail; t=1648635449; bh=e6BZQ6HMDm0LnZZNgl6hn1lNYpRIqXkvXdNGl7aWoRc=; h=Message-ID:Date:MIME-Version:Subject:To:References:From:In-Reply-To; b=Qeru4fVcwvdj6/AejFa8VSoqDd6fFtfjPrLTPLJdauMj25TPAteVNNAGuBOGq6a7UIW3QtI6TBKbD5s7RNj0pUKyfg7ezzW0oBzAViUnW3bCM33HzImCHpMSC+q/nbv9xjoD+0cbSThyPGG7QHTyXnCqTUnlTnLBsbRpv+bY9/QomdiJqsWrGnY72T59vDrjAoQSiY5SoAWkry0MwiJb66FXZQ/osQlRMc7COfPBjJZ6MBdyvKd+iRNh75HvfMfCXRLWJhkgNFJWa7QqOdMPDtyc82Y0ULcQ/KM+BvlloKBTA0rqWIQBM3fV5IMw0bT6y0GkW7VvDJ2zyn4Qur2LqQ== X-RG-Rigid: 61A8978C06F43CD9 X-Originating-IP: [84.216.97.240] X-RazorGate-Vade: gggruggvucftvghtrhhoucdtuddrgedvvddrudeivddgvdejucetufdoteggodetrfdotffvucfrrhhofhhilhgvmecuvffgnffktefuhgdpggftfghnshhusghstghrihgsvgdpqfgfvfenuceurghilhhouhhtmecufedttdenucesvcftvggtihhpihgvnhhtshculddquddttddmnegoufhushhpvggtthffohhmrghinhculdegledmnegoufhprghmkfhpqdhouhhtucdlhedttddmnecujfgurhepkfffgggfuffvfhfhjggtgfesthekredttdefjeenucfhrhhomhepuehjnphrnhgpnfgrrhhsshhonhcuoegsjhhorhhnrdigrdhlrghrshhsohhnsehtvghlihgrrdgtohhmqeenucggtffrrghtthgvrhhnpeekgeevgedugfffteegudduveeggedvvedtffevieffudegtddtgffgkeduleelveenucffohhmrghinhepfehvgehlrdhorhhgnecukfhppeekgedrvdduiedrleejrddvgedtnecuufhprghmkfhppeekgedrvdduiedrleejrddvgedtnecuvehluhhsthgvrhfuihiivgeptdenucfrrghrrghmpehhvghloheplgduledvrdduieekrddurdekngdpihhnvghtpeekgedrvdduiedrleejrddvgedtpdhmrghilhhfrhhomhepuhekleeltdeigedujeesphhnvgdrthgvlhhirgdrtghomhdpnhgspghrtghpthhtohepvddprhgtphhtthhopehinhhtvghrnhgrlhhssehlihhsthhsrdhphhhprdhnvghtpdhrtghpthhtoheprhhofigrnhdrtgholhhlihhnshesghhmrghilhdrtghomh X-RazorGate-Vade-Verdict: spam 449 X-RazorGate-Vade-Classification: spam Received: from [192.168.1.8] (84.216.97.240) by ts201-smtpout72.ddc.teliasonera.net (5.8.716) (authenticated as u89906417) id 61A8978C06F43CD9; Wed, 30 Mar 2022 12:17:28 +0200 Message-ID: <92302377-6a49-d754-1210-b926c7381962@telia.com> Date: Wed, 30 Mar 2022 12:17:29 +0200 MIME-Version: 1.0 User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:91.0) Gecko/20100101 Thunderbird/91.7.0 Content-Language: en-GB To: Rowan Tommins References: <9ecce8c9-c8bc-93e3-25f0-386c2c41ca1a@gmail.com> Cc: PHP Internals Reply-To: =?UTF-8?Q?Bj=c3=b6rn_Larsson?= In-Reply-To: <9ecce8c9-c8bc-93e3-25f0-386c2c41ca1a@gmail.com> Content-Type: text/plain; charset=UTF-8; format=flowed Content-Transfer-Encoding: 8bit Subject: Re: Undefined variables and the array append operator From: internals@lists.php.net ("Björn Larsson via internals") Den 2022-03-29 kl. 21:44, skrev Rowan Tommins: > Hi all, > > If $foo is not defined, statements such as $foo += 1 and $foo .= 'blah' > raise "undefined variable" Warnings in PHP 8, and will throw Errors in > PHP 9. However, the very similar looking $foo[] = 1 succeeds silently. > > This seems odd to me, as "append to string" and "append to array" seem > like very similar operations, with most of the same use cases and > possible bugs. > > > From an *implementation* point of view, this is presumably because they > are defined as different Op Codes - ASSIGN_OP for .= and ASSIGN_DIM for > []=, I believe. But that doesn't explain *why* ASSIGN_DIM behaves this way. > > A *historical* explanation might relate to Perl's "autovivification" > feature. However, PHP does *not* implement the same rules as Perl: for > instance, Perl will create array dimensions just by reading them, which > PHP does not; and Perl has a completely different type system, with > cases like "a scalar becomes a reference to a hash unless already a > reference to a list". Note also that I'm *not* talking about > multi-dimensional arrays with missing keys here, only undefined local > variables, as were the subject of the recent RFC. > > The *observable behaviour* for most operators in PHP is the same: > > 1) if the variable is undefined, consider the value to be null > 2) coerce the value to the appropriate type; if the value is null, this > gives the relevant "empty" value, such as '', 0, or [] > 3) apply the operator > > There isn't anything particularly special with $foo[] = 'bar' in this > case, except that it's the only operator that doesn't raise a Warning > (and planned Error) at step 1. The same goes for all the other uses of > the [] syntax I can think of, like $foo['key'] = 'bar', or $ref =& $foo[]. > > > For example, consider the following simple validation code > [https://3v4l.org/pP5CU]: > > $requiredFields = ['name', 'age', 'hair_colour']; > > // Note: $errorString is not initialised > foreach ( $requiredFields as $field ) { >     if ( ! isset($_POST[$field]) ) { >         $errorString .= "Missing required field '$field'. "; >     } > } > echo $errorString; > > This gives an "Undefined variable" Notice / Warning / Error, depending > on the version. That's reasonable, as failing to initialise $errorString > might cause problems if this code is integrated into a loop or larger > function later. > > However, switch the code from building up a string to building up an > array, and the result is identical, but the Notice / Warning / Error > goes away [https://3v4l.org/ojZ1O]: > > // Note: $errorArray is not initialised > foreach ( $requiredFields as $field ) { >     if ( ! isset($_POST[$field]) ) { >         $errorArray[] = "Missing required field '$field'. "; >     } > } > echo implode('', $errorArray); > > > Can anyone give a compelling reason why we should keep this > inconsistency, or should I raise an RFC to bring it in line with other > undefined variable accesses? > > I think it deserves an RFC. Then we also capture your excellent explanation above! Regards //Björn L