7

We are upgrading to PHP 8.1. A new feature is that an undefined array key throws a warning.

Unfortunately this interferes with the ability to easily use associative arrays such as $_SESSION variables. I understand the virtues of predefining variables, and am not looking for a discussion on those virtues. The idea of the associative array is that you can add things easily to the session and everything not so assigned is evaluated as null. But now it also throws a warning; something has to be done to deal with that.

Here is an example of some code:

$_SESSION['is_condition'] = true;

In another place in the code, the following occurs

if ($_SESSION['is_condition']) ...

If this occurs in a context where the 'is_condition' session variable has not been defined, the desired result of evaluating its value as null is what we want. But now something else has to be done to deal with the possibility that it is undefined.

There are several approaches to dealing with this:

  1. Pre-define all session variables having the value of null. Seems like it is not the spirit of associative arrays. Now every script has to invoke a lengthy set of code.

  2. Use the null coalesce operator whenever the value of an associative array element is required. This is an ugly requirement to place many, many additional operators throughout the code base.

  3. Alter our custom error handling functions to ignore the undefined array key error. A very bad idea to suppress warnings, and adds overhead.

None of these approaches is very desirable.

A theoretical way to solve this would be an array initialization statement that assigns all possible associative keys to null. I don't know of any such thing.

My question is whether there is some other approach that I am missing, such as a parameter that suppresses this specific warning only.

Jeffrey Simon
  • 918
  • 3
  • 11
  • 25
  • 4
    You can also use [isset](https://www.php.net/isset), [array_key_exists](https://www.php.net/array_key_exists), and [!empty](https://www.php.net/manual/en/function.empty.php) – aynber Feb 07 '22 at 20:43
  • 6
    Undefined array indexes have always triggered a warning. I think it simple changed from `E_NOTICE` to `E_WARNING`. – Barmar Feb 07 '22 at 20:43
  • 1
    Most applications don't have lots of session variables that are assigned conditionally, so you shouldn't have to deal with this in lots of places. For those variables that you do, the null coalesce operator is the simplest solution. – Barmar Feb 07 '22 at 20:44
  • Does this answer your question? [Best way to handle Undefined array key in PHP 8.0](https://stackoverflow.com/questions/70549291/best-way-to-handle-undefined-array-key-in-php-8-0) – Martin Feb 07 '22 at 20:54

3 Answers3

4

The cleanest way to fix this would be replacing

if ($_SESSION['is_condition'])

with

if ($_SESSION['is_condition'] ?? false)
DaveFX
  • 407
  • 1
  • 8
  • 16
3

My suggestion would be to write an abstraction over the session mechanism that deals with this problem. I'd opt for a class, but even a simple function could work:

function getValueFromSession(string $key, mixed $defaultValue = null) : mixed
{
   return isset($_SESSION[$key]) ? $_SESSION[$key] : $defaultValue;
}

This has the added benefit of allowing you to change your underlying session storage (e.g. to Redis) without having to change every single instance of session value access.

jhmckimm
  • 870
  • 6
  • 15
  • While I like this approach in general, it has the downside of invoking the function call whenever the value is needed. For example, some session variables are accessed dozens of times in a single script. So you have to call that function for all these occurrences. – Jeffrey Simon Apr 12 '22 at 22:23
  • @JeffreySimon you're not really going to get around having to do that. It's not particularly expensive and is clean, succinct, sane code. – jhmckimm Apr 22 '22 at 11:20
  • 1
    be careful with this: `isset($_SESSION[$key])` will throw a warning on php 8 if index is not defined – maztch Oct 13 '22 at 12:52
  • 1
    `$key` is a string. It is required to be declared by the function signature. I would personally use `key_exists()` as the check so that `null` can be respected without falling back to the default value. – mickmackusa Nov 04 '22 at 06:58
0

You are assuming that $_SESSION['whatever'] is always going to be available. You can wrap all your conditionals with isset like so:

if (isset($_SESSION['is_condition'])) {
//Do Whatever
}

Or you can do something unweildy like putting this at the top of your file.

if (isset($_SESSION['is_condition'])) {
//Do something
} else {
$_SESSION['is_condition'] = NULL;
} 

From then on anytime you check the session for that key it will at least be set to something and wont throw a warning or notice. It's ugly but it will work.

Nicholas Koskowski
  • 793
  • 1
  • 4
  • 23
  • Note that these if blocks will execute as long as there is a value within the session variable, even if that value is `false`. Use `if (isset($_SESSION['var']) && $_SESSION['var'])` to prevent. – jhmckimm Feb 07 '22 at 20:53
  • The first suggestion would work in some cases and in fact we use it sometimes, but in the case of a structure like the following, would be unwieldy: if ($_SESSION['a'] || $_SESION['b']) .... That is because in some instances there could be 20 or more such conditions. The second suggestion is ugly, but is in fact what we are doing now. However, with the syntactical sugar as follows: $_SESSION['a'] = $_SESSION['a'] ?? null; – Jeffrey Simon Apr 12 '22 at 22:25
  • it make another problem, because passing null/empty values in php 8 is depreciated – zoore Mar 08 '23 at 11:24