Categories
arrays php undefined-index variables warnings

“Notice: Undefined variable”, “Notice: Undefined index”, “Warning: Undefined array key”, and “Notice: Undefined offset” using PHP

1331

I’m running a PHP script and continue to receive errors like:

Notice: Undefined variable: my_variable_name in C:\wamp\www\mypath\index.php on line 10

Notice: Undefined index: my_index C:\wamp\www\mypath\index.php on line 11

Warning: Undefined array key “my_index” in C:\wamp\www\mypath\index.php on line 11

Line 10 and 11 looks like this:

echo "My variable value is: " . $my_variable_name;
echo "My index value is: " . $my_array["my_index"];

What is the meaning of these error messages?

Why do they appear all of a sudden? I used to use this script for years and I’ve never had any problem.

How do I fix them?


This is a General Reference question for people to link to as duplicate, instead of having to explain the issue over and over again. I feel this is necessary because most real-world answers on this issue are very specific.

Related Meta discussion:

12

  • 14

    possible duplicate of Reference – What does this error mean in PHP?

    – user229044

    Oct 8, 2013 at 15:25

  • 4

    the variable might not have been initialized. Are you initializing the variable from a post or get or any array? If that’s the case you might not have an field in that array. That your accessing.

    Dec 15, 2015 at 13:12

  • 4

    @Pekka웃 – I noticed the edit adding the “and “Notice: Undefined offset”” – Wouldn’t it make more sense using “PHP: “Undefined variable”, “Undefined index”, “Undefined offset” notices” (even take out the PHP, since it is tagged as “php”. Plus, the URL gets cut off at and-notice-undef, just a suggestion so that the URL doesn’t get cut off. Maybe even removing the (too many) quotes. Or PHP: “Undefined variable/index/offset” notices

    Jan 20, 2017 at 15:24


  • 3

    @Fred I guess an argument can be made for both variations. THere’s a chance that newbies will enter the entire line, including the “Notice:” into their search query, which I’m sure is the main traffic generator for this question. If the messages are there in full, that’s likely to improve visibility in search engines

    – Pekka

    Jan 20, 2017 at 15:34


  • 3

    @Pekka웃 I understand. I only said that because the URL didn’t get cut off before and now it does at and-notice-undef. It was just a (few) suggestion(s). It just repeats itself also being Notice: Undefined.

    Jan 20, 2017 at 15:35


1187

Notice / Warning: Undefined variable

From the vast wisdom of the PHP Manual:

Relying on the default value of an uninitialized variable is problematic in the case of including one file into another which uses the same variable name. It is also a major security risk with register_globals turned on. E_NOTICE level error is issued in case of working with uninitialized variables, however not in the case of appending elements to the uninitialized array. isset() language construct can be used to detect if a variable has been already initialized. Additionally and more ideal is the solution of empty() since it does not generate a warning or error message if the variable is not initialized.

From PHP documentation:

No warning is generated if the variable does not exist. That means
empty() is essentially the concise equivalent to !isset($var) || $var
== false
.

This means that you could use only empty() to determine if the variable is set, and in addition it checks the variable against the following, 0, 0.0, "", "0", null, false or [].

Example:

$o = [];
@$var = ["",0,null,1,2,3,$foo,$o['myIndex']];
array_walk($var, function($v) {
    echo (!isset($v) || $v == false) ? 'true ' : 'false';
    echo ' ' . (empty($v) ? 'true' : 'false');
    echo "\n";
});

Test the above snippet in the 3v4l.org online PHP editor

Although PHP does not require a variable declaration, it does recommend it in order to avoid some security vulnerabilities or bugs where one would forget to give a value to a variable that will be used later in the script. What PHP does in the case of undeclared variables is issue a very low level error, E_NOTICE, one that is not even reported by default, but the Manual advises to allow during development.

Ways to deal with the issue:

  1. Recommended: Declare your variables, for example when you try to append a string to an undefined variable. Or use isset() / !empty() to check if they are declared before referencing them, as in:

    //Initializing variable
    $value = ""; //Initialization value; Examples
                 //"" When you want to append stuff later
                 //0  When you want to add numbers later
    //isset()
    $value = isset($_POST['value']) ? $_POST['value'] : '';
    //empty()
    $value = !empty($_POST['value']) ? $_POST['value'] : '';
    

This has become much cleaner as of PHP 7.0, now you can use the null coalesce operator:

    // Null coalesce operator - No need to explicitly initialize the variable.
    $value = $_POST['value'] ?? '';
  1. Set a custom error handler for E_NOTICE and redirect the messages away from the standard output (maybe to a log file):

    set_error_handler('myHandlerForMinorErrors', E_NOTICE | E_STRICT)
    
  2. Disable E_NOTICE from reporting. A quick way to exclude just E_NOTICE is:

    error_reporting( error_reporting() & ~E_NOTICE )
    
  3. Suppress the error with the @ operator.

Note: It’s strongly recommended to implement just point 1.

Notice: Undefined index / Undefined offset / Warning: Undefined array key

This notice/warning appears when you (or PHP) try to access an undefined index of an array.

Ways to deal with the issue:

  1. Check if the index exists before you access it. For this you can use isset() or array_key_exists():

    //isset()
    $value = isset($array['my_index']) ? $array['my_index'] : '';
    //array_key_exists()
    $value = array_key_exists('my_index', $array) ? $array['my_index'] : '';
    
  2. The language construct list() may generate this when it attempts to access an array index that does not exist:

    list($a, $b) = array(0 => 'a');
    //or
    list($one, $two) = explode(',', 'test string');
    

Two variables are used to access two array elements, however there is only one array element, index 0, so this will generate:

Notice: Undefined offset: 1

#$_POST / $_GET / $_SESSION variable

The notices above appear often when working with $_POST, $_GET or $_SESSION. For $_POST and $_GET you just have to check if the index exists or not before you use them. For $_SESSION you have to make sure you have the session started with session_start() and that the index also exists.

Also note that all 3 variables are superglobals and are uppercase.

Related:

11

  • 9

    @dieselpower44 A couple of thoughts: The “shut-up operator” (@) has some performance issues. Also, since it suppresses all errors within a particular scope, using it without care might mask messages you wish you’d seen.

    – IMSoP

    Oct 24, 2013 at 20:00

  • 6

    Hiding the issues is NOT the way to deal with issues. Items #2…#4 can be used only on production servers, not in general.

    – Salman A

    Sep 13, 2014 at 8:09


  • 1

    Is it possible to shut-up the message inline (not in handler) when also a custom error handler is used? $var = @$_GET['nonexisting']; still causes notice..

    – Slava

    Oct 11, 2014 at 14:14


  • 21

    Why is it recommended to use 1. $value = isset($_POST['value']) ? $_POST['value'] : ''; instead of using 4. $value = @$_POST['value'];?

    Feb 9, 2015 at 13:38

  • 2

    I don’t recommend using isset() for arrays, e.g. $str = '111';, (I know it should be array) isset($str[0]) will return true. It’s better off using array_key_exist() instead of isset()

    – M Rostami

    Nov 17, 2016 at 20:01

164

Try these

Q1: this notice means $varname is not
defined at current scope of the
script.

Q2: Use of isset(), empty() conditions before using any suspicious variable works well.

// recommended solution for recent PHP versions
$user_name = $_SESSION['user_name'] ?? '';

// pre-7 PHP versions
$user_name="";
if (!empty($_SESSION['user_name'])) {
     $user_name = $_SESSION['user_name'];
}

Or, as a quick and dirty solution:

// not the best solution, but works
// in your php setting use, it helps hiding site wide notices
error_reporting(E_ALL ^ E_NOTICE);

Note about sessions:

4

  • If using E_NOTICE from the php.ini configuration file, do error_reporting = (E_ALL & ~E_NOTICE)

    – ahmd0

    Oct 4, 2014 at 5:39

  • 1

  • From the above answer, I have tried isset, array_key_exists but those didn’t work. I tried your answer, .empty(), and it works. Thank you very much!

    – user13137957

    Apr 24, 2020 at 20:53

  • Thank you so much . I have add “error_reporting(E_ALL ^ E_NOTICE); ” this is working to me .

    – Ganesan J

    Jul 2 at 4:48


77

Error display @ operator

For undesired and redundant notices, one could use the dedicated @ operator to »hide« undefined variable/index messages.

$var = @($_GET["optional_param"]);
  • This is usually discouraged. Newcomers tend to way overuse it.
  • It’s very inappropriate for code deep within the application logic (ignoring undeclared variables where you shouldn’t), e.g. for function parameters, or in loops.
  • There’s one upside over the isset?: or ?? super-supression however. Notices still can get logged. And one may resurrect @-hidden notices with: set_error_handler("var_dump");
    • Additonally you shouldn’t habitually use/recommend if (isset($_POST["shubmit"])) in your initial code.
    • Newcomers won’t spot such typos. It just deprives you of PHPs Notices for those very cases. Add @ or isset only after verifying functionality.
    • Fix the cause first. Not the notices.

  • @ is mainly acceptable for $_GET/$_POST input parameters, specifically if they’re optional.

And since this covers the majority of such questions, let’s expand on the most common causes:

$_GET / $_POST / $_REQUEST undefined input

  • First thing you do when encountering an undefined index/offset, is check for typos:
    $count = $_GET["whatnow?"];

    • Is this an expected key name and present on each page request?
    • Variable names and array indicies are case-sensitive in PHP.
  • Secondly, if the notice doesn’t have an obvious cause, use var_dump or print_r to verify all input arrays for their curent content:

    var_dump($_GET);
    var_dump($_POST);
    //print_r($_REQUEST);
    

    Both will reveal if your script was invoked with the right or any parameters at all.

  • Alternativey or additionally use your browser devtools (F12) and inspect the network tab for requests and parameters:

    browser developer tools / network tab

    POST parameters and GET input will be be shown separately.

  • For $_GET parameters you can also peek at the QUERY_STRING in

    print_r($_SERVER);
    

    PHP has some rules to coalesce non-standard parameter names into the superglobals. Apache might do some rewriting as well.
    You can also look at supplied raw $_COOKIES and other HTTP request headers that way.

  • More obviously look at your browser address bar for GET parameters:

    http://example.org/script.php?id=5&sort=desc

    The name=value pairs after the ? question mark are your query (GET) parameters. Thus this URL could only possibly yield $_GET["id"] and $_GET["sort"].

  • Finally check your <form> and <input> declarations, if you expect a parameter but receive none.

    • Ensure each required input has an <input name=FOO>
    • The id= or title= attribute does not suffice.
    • A method=POST form ought to populate $_POST.
    • Whereas a method=GET (or leaving it out) would yield $_GET variables.
    • It’s also possible for a form to supply action=script.php?get=param via $_GET and the remaining method=POST fields in $_POST alongside.
    • With modern PHP configurations (≥ 5.6) it has become feasible (not fashionable) to use $_REQUEST['vars'] again, which mashes GET and POST params.
  • If you are employing mod_rewrite, then you should check both the access.log as well as enable the RewriteLog to figure out absent parameters.

$_FILES

  • The same sanity checks apply to file uploads and $_FILES["formname"].
  • Moreover check for enctype=multipart/form-data
  • As well as method=POST in your <form> declaration.
  • See also: PHP Undefined index error $_FILES?

$_COOKIE

  • The $_COOKIE array is never populated right after setcookie(), but only on any followup HTTP request.
  • Additionally their validity times out, they could be constraint to subdomains or individual paths, and user and browser can just reject or delete them.

3

  • 2

    If you are curious what is the performance impact, this article summarises it well, derickrethans.nl/….

    – Gajus

    Feb 11, 2014 at 12:24

  • @GajusKuizinas There have been quoite a few changes since 2009, in particular php.net/ChangeLog-5.php#5.4.0 changes the outcome drastically (see “Zend Engine, performance” and “(silence) operator”).

    – mario

    Feb 11, 2014 at 12:37

  • Thanks @mario, interesting. Now, if someone was good enough to benchmark the two… 3v4l.org/CYVOn/perf#tabs 3v4l.org/FLp3D/perf#tabs According to this test, seem to be identical (notice that scale changes).

    – Gajus

    Feb 11, 2014 at 16:30