0

With PHP 8 The concept of an unfound array key was promoted from a NOTICE error level to a WARNING error level.

This causes us huge code and error_log bloats where we turn off notices and retain warnings on error logs which end up being filled with repetative warnings about array key existance.

For example; Some code to check if a SESSION value exists and if so then use it in some local code. SESSION value is set in some other part of the website and is dynamically set.

<?php
// This code is server side action example

include whatever_header.php //sets session start etc.

if($_SESSION['action'] === "submit"){
...
}

$localPageDataArray = $_SESSION['core']['data']?:['default' => 'no'];

Previous to PHP 8, if $_SESSION action was not set it didn't matter, because the if condition only executed if it was set to a specific value. To be clear; if $_SESSION['action'] was never set then the code would work in exactly the same way as if $_SESSION['action'] === "sleep" , ie various conditionals would still fire or not fire accordingly.

NOW, the error logs blow up with various warnings such as:

PHP Warning: Undefined array key "action" in /home/public_html/session_test_script.php on line 5
PHP Warning: Undefined array key "data" in /home/public_html/session_test_script.php on line 9

There are a couple of issues with this warning feedback:

  1. It blows up and hugely inflates the error logs

  2. It causes huge code bloat to workaround this issue:

Example of code bloat being to resolve the above warning would be:

<?php
// This code is server side action example

include whatever_header.php //sets session start etc.

if(array_key_exists('action',$_SESSION) && $_SESSION['action'] === "submit"){
...
}

Or even worse:

<?php
// This code is server side action example

include whatever_header.php //sets session start etc.

if(array_key_exists('action',$_SESSION) && $_SESSION['action'] === "submit"){
...
}

$localPageDataArray = ['default' => 'no']; //default value if below IF is false
if(array_key_exists($_SESSION,'core') && is_array($_SESSION['core']) 
   && array_key_exists($_SESSION['core'],'data') {
   $localPageDataArray = $_SESSION['core']['data']?:['default' => 'no'];
}

This is a huge bloat on the code for absolutely zero benefit aside from removing tedious warning messages from the error logs. Because the issue has been promoted to WARNING level then we can't realistically turn of WARNING logs as that's a bad idea for genuine warnings.

While we can slightly streamline the above to being an isset check thus:

if(isset($_SESSION['core']['data']) && is_array($_SESSION['core']['data'])) {
   $localPageDataArray = $_SESSION['core']['data']?:['default' => 'no'];
}

This still greatly inflates the code size for zero practical improvment.

Question

Are there any workarounds to how to easily and efficiently avoid these Warning error log messages without having to deal with multiple lines of hard coding checking processes?

Note that these issues are due to $_SESSION (and sometimes other superglobal data) being dynamically generated so we can't always ensure that a value exists and that's built into the default checking mechanisms as illustrated here.

If we can do the above with one line, this would be a great compromise:

$localPageDataArray = isset($_SESSION['core']['data'])?$_SESSION['core']['data']:['default' => 'no'];

BUT This only sets the default value (['default' => 'no']) if the $_SESSION['core']['data'] is not set, rather than if it is set and is empty

Not a Dupe

This question is not a dupe because I'm not caring about speed (although it's nice isset is so fast) but asking about how to avoid the error_log Warning messages found in PHP 8+ which are a different issue to speed.

Martin
  • 22,212
  • 11
  • 70
  • 132
  • 2
    `for absolutely zero benefit`...in general this principle makes your code more reliable and robust and correct, and should reduce the possibility for unexpected bugs when values are missing. – ADyson Feb 17 '23 at 14:07
  • @ADyson, well, no because for example if the `if` statement contains the value it is checking (`$_SESSION['action'] === "submit"`) then that triggers but in all other cases - *including if the array key doesn't exist* - there's no need to check if the array keys exist; it's verbose and doesn't do anything to help the code. This is especially problematic for us when many session keys are dynamically generated by the user-journey on the website and having to check when each one exists simply to come to the same conclusion (`if` logic failed) is worthless. – Martin Feb 17 '23 at 14:17
  • @Martin : `if (isset($_SESSION['action']) && $_SESSION['action'] === "submit")` – Cid Feb 17 '23 at 14:18
  • (( My core problem is that this NOTICE has been elevated to WARNING level so we can't / shouldn't turn it off in the error reporting. )) – Martin Feb 17 '23 at 14:18
  • @Cid yes we've used that a few times; does that throw any warnings if any of the keys doesn't exist? ie `if(isset($_SESSION['keyouter']['keyinner']) && $_SESSION['keyouter']['keyinner'] === 'yes'){...` I will check.... – Martin Feb 17 '23 at 14:19
  • @Martin there's a difference between the array key not existing, and it not containing a specific value. Maybe it doesn't matter for your specific use case, but it might in some circumstances, and that can lead to unexpected behaviour potentially. I believe the PHP developers are trying to make the language more robust, drive up code quality of what regular developers write, and move it more towards how most OO / strongly-typed languages work. In general it should make things better, although perhaps in this case at the cost of a bit of extra effort. – ADyson Feb 17 '23 at 14:21
  • @Cid yes `isset` seems to work and to cause no errors if any keys don't exist. Thanks. – Martin Feb 17 '23 at 14:22
  • @Cid feel free to set it in an answer :) – Martin Feb 17 '23 at 14:22
  • @Martin that's probably a dupe – Cid Feb 17 '23 at 14:23
  • 1
    Does this answer your question? [What's quicker and better to determine if an array key exists in PHP?](https://stackoverflow.com/questions/700227/whats-quicker-and-better-to-determine-if-an-array-key-exists-in-php) – Cid Feb 17 '23 at 14:25
  • 1
    Note that `isset()` will return `false` if the key exists and holds the value `null` – Cid Feb 17 '23 at 14:27
  • @ADyson "might in some circumstances" is a bit of an affliction to stomach. I'm not really griping at you -- it's the PHP Devs decision to promote missing array keys to Warnings; whereas much PHP code can flexibly accept that if a key doesn't exist then any [positive] comparison will always fail, and vice versa. Anyways.... I just wasn't certain if I knew the best way to mitigate this error logging but Cid's reference to `isset` seems to work as it doesn't raise errors for if the keys don't exist `:-)` – Martin Feb 17 '23 at 14:27
  • There's another way, but I **strongly** discourage you for using it : You can prepend the array with the [Error Control Operators : `@`](https://www.php.net/manual/en/language.operators.errorcontrol.php) : `if (@$_SESSION['action'] == 'something')` but it's a bad practice, always use proper checkings (I just mention it for your information) – Cid Feb 17 '23 at 14:31
  • @Cid I would like you to answer this question specifically because it's not a dupe because I'm not caring about speed (although it's nice `isset` is so fast) but asking about how to avoid the error_log warning messages which are a different issue to speed. Thanks :) – Martin Feb 17 '23 at 14:31
  • @Cid we have actually made our own error logging interface to use which manually checks if the warning is "undefined array key" and then ignores the warning if so – Martin Feb 17 '23 at 14:33
  • 1
    `$localPageDataArray = isset($_SESSION['core']['data'])?$_SESSION['core']['data']:['default' => 'no'];` can be reduced to `$localPageDataArray = $_SESSION['core']['data']) ?? ['default' => 'no'];` Without [warnings](https://onlinephp.io/c/42a30) Check [this](https://stackoverflow.com/questions/53610622/what-does-double-question-mark-operator-mean-in-php/53610731#53610731) – Cid Feb 17 '23 at 14:34
  • @Martin I agree it's annoying for you, and I'm not necessarily fully on the side of the PHP devs, but off the top of my head here's a (admittedly confected) example where the difference between undefined and "some other value" might become important, and should be highlighted to the developer: https://3v4l.org/gS5G3 . In a stricter language (e.g. C# or Java) it would be a fatal error. – ADyson Feb 17 '23 at 14:34

1 Answers1

1

With the help of Cid a minimal coded solution would be to use ?? Null coalescing operator and/or isset to check values are set without getting strung up on intermediate array keys in multidimensional arrays.

e.g:

if(isset($_SESSION['action']) && $_SESSION['action'] === "submit"){
   ...
}

$localPageDataArray = $_SESSION['core']['data']??['default' => 'no'];

Neither of these tests will now produce Warnings about undefined array keys

Martin
  • 22,212
  • 11
  • 70
  • 132