Newsgroups: php.internals Path: news.php.net Xref: news.php.net php.internals:117446 Return-Path: Delivered-To: mailing list internals@lists.php.net Received: (qmail 99859 invoked from network); 29 Mar 2022 18:15:56 -0000 Received: from unknown (HELO php-smtp4.php.net) (45.112.84.5) by pb1.pair.com with SMTP; 29 Mar 2022 18:15:56 -0000 Received: from php-smtp4.php.net (localhost [127.0.0.1]) by php-smtp4.php.net (Postfix) with ESMTP id 507051804A9 for ; Tue, 29 Mar 2022 12:44:14 -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_20,BODY_8BITS, 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-wm1-f41.google.com (mail-wm1-f41.google.com [209.85.128.41]) (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 ; Tue, 29 Mar 2022 12:44:13 -0700 (PDT) Received: by mail-wm1-f41.google.com with SMTP id p189so10983471wmp.3 for ; Tue, 29 Mar 2022 12:44:13 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20210112; h=message-id:date:mime-version:user-agent:content-language:from :subject:to:content-transfer-encoding; bh=s/j0pxCOpASSJ9vPr4pfp1LVMnnRSWfdAcE7lCcS6CU=; b=j1cXly6BKaqE/jGZMytJpKD5FCduXf0yHk5s8LSPxGnR/fgPV9Pmg51vNFIp/WCn87 gEgGvgUVOj6qBQhO77yQNbqs7/5DiOVX2I7KNKpLdeMJdMx6bTU9jsLn4x4CdXp9Kj97 LjDgVVLOsKtxDrHxAWB+Pe4hochcsfY7hxngGaZ+IHQXMaXNoxLqdorMNx66hODvLFow FasRLqeMXQlBj8uECOg4d99MBZqvuP8Wnf8l7qv+cRTg7om1XdUQx28Dt/eKgaoejjmt RKV2PgvZMotP6G71ZT6qUiDoYWT7ATOZF3weumuiqu7gd2xoiH+A3znQUvvlKLEUzv+f KQ+g== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:message-id:date:mime-version:user-agent :content-language:from:subject:to:content-transfer-encoding; bh=s/j0pxCOpASSJ9vPr4pfp1LVMnnRSWfdAcE7lCcS6CU=; b=ml5Bw+U96U4AhiCMC6unMjMO2Rt0Rx79WF/YGEQvMLN9HApFcfyu2crzMQqwKlwEkw pSNLN2V6wOExA3r+1MyEHr0GouwXfHFBHHvnRhf0hDvAYmGqP7YmNZBnhKaMPijsL+tF xxUzNcJJBAcWphANguUU7P0YeN/3+yOG/dAXxKQioPj2ywMUYecavbD8xhP8bCLK1z/y Lv5vrbcMY7oVXK5Nl0OI+GcSrEIraY1d4iB7kjiXSCA55zmU/9cbPRNlqQHtkpI5twpf Beav2SNLIrh0KHucYZymyZxrvRS7ldnG8M3PKKTV/aXOT35BBVTYkOOWb2qTIFGbpm9d aCIg== X-Gm-Message-State: AOAM531vd3yARl2wwAi8upPxoReI5YI7lY4sqH0RoBdKbM5wWphcKb3B Tit8f3tGihWeIVhI5j1+Sc/r3WFEcOU= X-Google-Smtp-Source: ABdhPJzCOqxPPbSGcB6Nwf7GmmpbmS/uuLa2B9eiT3YCJ41dtCS5bGlATkBpKPtFqZovDUKORmLaLw== X-Received: by 2002:a05:600c:204:b0:38d:bad:7552 with SMTP id 4-20020a05600c020400b0038d0bad7552mr1109274wmi.133.1648583052314; Tue, 29 Mar 2022 12:44:12 -0700 (PDT) Received: from [192.168.0.22] (cpc104104-brig22-2-0-cust548.3-3.cable.virginm.net. [82.10.58.37]) by smtp.googlemail.com with ESMTPSA id z3-20020a1cf403000000b0037d1f4a2201sm2949930wma.21.2022.03.29.12.44.11 for (version=TLS1_3 cipher=TLS_AES_128_GCM_SHA256 bits=128/128); Tue, 29 Mar 2022 12:44:11 -0700 (PDT) Message-ID: <9ecce8c9-c8bc-93e3-25f0-386c2c41ca1a@gmail.com> Date: Tue, 29 Mar 2022 20:44:11 +0100 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: PHP Internals Content-Type: text/plain; charset=UTF-8; format=flowed Content-Transfer-Encoding: 8bit Subject: Undefined variables and the array append operator From: rowan.collins@gmail.com (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? Regards, -- Rowan Tommins [IMSoP]