Newsgroups: php.internals Path: news.php.net Xref: news.php.net php.internals:117449 Return-Path: Delivered-To: mailing list internals@lists.php.net Received: (qmail 31044 invoked from network); 30 Mar 2022 06:44:14 -0000 Received: from unknown (HELO php-smtp4.php.net) (45.112.84.5) by pb1.pair.com with SMTP; 30 Mar 2022 06:44:14 -0000 Received: from php-smtp4.php.net (localhost [127.0.0.1]) by php-smtp4.php.net (Postfix) with ESMTP id 077421804A9 for ; Wed, 30 Mar 2022 01:12:40 -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=-2.1 required=5.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,FREEMAIL_FROM, RCVD_IN_DNSWL_NONE,RCVD_IN_MSPIKE_H2,SPF_HELO_NONE,SPF_PASS, T_SCC_BODY_TEXT_LINE autolearn=no autolearn_force=no version=3.4.2 X-Spam-ASN: AS15169 209.85.128.0/17 X-Spam-Virus: No X-Envelope-From: Received: from mail-pg1-f176.google.com (mail-pg1-f176.google.com [209.85.215.176]) (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 01:12:39 -0700 (PDT) Received: by mail-pg1-f176.google.com with SMTP id c11so16978993pgu.11 for ; Wed, 30 Mar 2022 01:12:39 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20210112; h=mime-version:references:in-reply-to:from:date:message-id:subject:to :cc; bh=wCmNsPyeV730YTe/Tdv9om1XvfvpPOTrUtJlk6QfU6I=; b=H1kI1hlSUxKK/dMRIaYrUbT1UK+9e1tbiSxktMzNVG6mvv3ReeKJnyj3foSizmFYVv Y1rLFJ6u3oj/7hEvXnsrzm01eBhH4tGWEg9BBUUk7Jm9ZV6X6jw27tLrEVUU4UtBMeq4 oMa3lERBjQ0p8eKwS7FdOQZkTpFAYlFMeVcCCp+urfpiTIvPHsaouIdQexvsb1ixhgzV ZnrgfCxQ37tOMj3LrL/J8xa5PefTGGhIJ8Z9m/f1qeKVUw4yUH9s8DGWnWgemypKoYUK KmfBdZOKcOxzXl6v1/E36t85oK+HmiwIHP/CzsCfoS70wuugCGndHJaaWg/0VQsPAiN1 f14Q== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:mime-version:references:in-reply-to:from:date :message-id:subject:to:cc; bh=wCmNsPyeV730YTe/Tdv9om1XvfvpPOTrUtJlk6QfU6I=; b=3Yqy3Bm+UrDihx30pLouL2k8p+Zc1EKn9cTI+wxTCT2aENIcLnD3AWrwBWnWu42Guk pajgqVIQlez46GiJW5+T7YIpPnoVc71TwyW7oladiLalMgXrGG3VpnCPXzhjeZLHgbD1 rAUb9ChtUVDBLR1cL6TGxQNuvt5qKOuufCwBE0b80jgwYME1B/e8x8QfX81+xl6N+SSH XvUgJWexBuXTB87j4v10KRCtqwABkJkNywuVhLpIb0qITG+Eaarpx4hZ2RsaSvwf70up IIxkUEyRncSrb0kY8QWNqsDaDgzSaYNm0KZNu+DnkWPCHwCFoQeeENkWYN28OlJwL877 MaQg== X-Gm-Message-State: AOAM532mJmnUnBrzEAp+BnyaE6OnnXu2zEfsGXAFDK/iksv5d9kpVVjS iXigcj6x1ueOqt/Zo2K2J8PjcJazjZoOP8Et00g= X-Google-Smtp-Source: ABdhPJxn1bzkoC+MyAwfWyjhq6RwepuhQ0kI9i/6/TWnF2SQaFVfFMsLdehjUHB5EQBfWlT/gWnrKjKf5kqtjR1zcd4= X-Received: by 2002:a65:5a0d:0:b0:381:3c1e:9aca with SMTP id y13-20020a655a0d000000b003813c1e9acamr5220757pgs.562.1648627957972; Wed, 30 Mar 2022 01:12:37 -0700 (PDT) MIME-Version: 1.0 References: <9ecce8c9-c8bc-93e3-25f0-386c2c41ca1a@gmail.com> In-Reply-To: <9ecce8c9-c8bc-93e3-25f0-386c2c41ca1a@gmail.com> Date: Wed, 30 Mar 2022 10:12:27 +0200 Message-ID: To: Rowan Tommins Cc: PHP Internals Content-Type: text/plain; charset="UTF-8" Subject: Re: [PHP-DEV] Undefined variables and the array append operator From: landers.robert@gmail.com (Robert Landers) On Tue, Mar 29, 2022 at 9:44 PM Rowan Tommins wrote: > > 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? > > > Regards, > > -- > Rowan Tommins > [IMSoP] > > -- > PHP Internals - PHP Runtime Development Mailing List > To unsubscribe, visit: https://www.php.net/unsub.php > I think it's worth raising an RFC. There are other inconsistencies as well now, depending on how the undefined variable comes to exist, particularly around arrays. For example: $x = null; $a = $x['nope']; echo $a; There should be an error here, but $a gets the value null and only a warning is issued. Yet, this is already an error: $x = new class { public string|null $nope; }; $a = $x->nope; echo $a; So, depending on how you json_decode() you may or may not have issues.