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

后端 未结 28 911
盖世英雄少女心
盖世英雄少女心 2021-01-24 14:18

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

相关标签:
28条回答
  • 2021-01-24 14:54

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

    It is very common for most sites to operate under the "default" error reporting of "Show all errors, but not 'notices' and 'deprecated'". This will be set in php.ini and apply to all sites on the server. This means that those "notices" used in the examples will be suppressed (hidden) while other errors, considered more critical, will be shown/recorded.

    The other critical setting is the errors can be hidden (i.e. display_errors set to "off" or "syslog").

    What will have happened in this case is that either the error_reporting was changed to also show notices (as per examples) and/or that the settings were changed to display_errors on screen (as opposed to suppressing them/logging them).

    Why have they changed?

    The obvious/simplest answer is that someone adjusted either of these settings in php.ini, or an upgraded version of PHP is now using a different php.ini from before. That's the first place to look.

    However it is also possible to override these settings in

    • .htconf (webserver configuration, including vhosts and sub-configurations)*
    • .htaccess
    • in php code itself

    and any of these could also have been changed.

    There is also the added complication that the web server configuration can enable/disable .htaccess directives, so if you have directives in .htaccess that suddenly start/stop working then you need to check for that.

    (.htconf / .htaccess assume you're running as apache. If running command line this won't apply; if running IIS or other webserver then you'll need to check those configs accordingly)

    Summary

    • Check error_reporting and display_errors php directives in php.ini has not changed, or that you're not using a different php.ini from before.
    • Check error_reporting and display_errors php directives in .htconf (or vhosts etc) have not changed
    • Check error_reporting and display_errors php directives in .htaccess have not changed
    • If you have directive in .htaccess, check if they are still permitted in the .htconf file
    • Finally check your code; possibly an unrelated library; to see if error_reporting and display_errors php directives have been set there.
    0 讨论(0)
  • 2021-01-24 14:55

    Using a ternary is simple, readable, and clean:

    Pre PHP 7
    Assign a variable to the value of another variable if it's set, else assign null (or whatever default value you need):

    $newVariable = isset($thePotentialData) ? $thePotentialData : null;
    

    PHP 7+
    The same except using Null Coalescing Operator. There's no longer a need to call isset() as this is built in, and no need to provide the variable to return as it's assumed to return the value of the variable being checked:

    $newVariable = $thePotentialData ?? null;
    

    Both will stop the Notices from the OP question, and both are the exact equivalent of:

    if (isset($thePotentialData)) {
        $newVariable = $thePotentialData;
    } else {
        $newVariable = null;
    }
    

     
    If you don't require setting a new variable then you can directly use the ternary's returned value, such as with echo, function arguments, etc:

    Echo:

    echo 'Your name is: ' . isset($name) ? $name : 'You did not provide one';
    

    Function:

    $foreName = getForeName(isset($userId) ? $userId : null);
    
    function getForeName($userId)
    {
        if ($userId === null) {
            // Etc
        }
    }
    

    The above will work just the same with arrays, including sessions etc, replacing the variable being checked with e.g.:
    $_SESSION['checkMe']
    or however many levels deep you need, e.g.:
    $clients['personal']['address']['postcode']


     

    Suppression:

    It is possible to suppress the PHP Notices with @ or reduce your error reporting level, but it does not fix the problem, it simply stops it being reported in the error log. This means that your code still tried to use a variable that was not set, which may or may not mean something doesn't work as intended - depending on how crucial the missing value is.

    You should really be checking for this issue and handling it appropriately, either serving a different message, or even just returning a null value for everything else to identify the precise state.

    If you just care about the Notice not being in the error log, then as an option you could simply ignore the error log.

    0 讨论(0)
  • 2021-01-24 14:55

    These errors occur whenever we are using a variable that is not set.

    The best way to deal with these is set error reporting on while development.

    To set error reporting on:

    ini_set('error_reporting', 'on');
    ini_set('display_errors', 'on');
    error_reporting(E_ALL);
    

    On production servers, error reporting is off, therefore, we do not get these errors.

    On the development server, however, we can set error reporting on.

    To get rid of this error, we see the following example:

    if ($my == 9) {
     $test = 'yes';  // Will produce error as $my is not 9.
    }
    echo $test;
    

    We can initialize the variables to NULL before assigning their values or using them.

    So, we can modify the code as:

    $test = NULL;
    if ($my == 9) {
     $test = 'yes';  // Will produce error as $my is not 9.
    }
    echo $test;
    

    This will not disturb any program logic and will not produce Notice even if $test does not have value.

    So, basically, its always better to set error reporting ON for development.

    And fix all the errors.

    And on production, error reporting should be set to off.

    0 讨论(0)
  • 2021-01-24 14:56

    Probably you were using old PHP version until and now upgraded PHP thats the reason it was working without any error till now from years. until PHP4 there was no error if you are using variable without defining it but as of PHP5 onwards it throws errors for codes like mentioned in question.

    0 讨论(0)
  • 2021-01-24 14:58

    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:

    • When using sessions, session_start(); is required to be placed inside all files using sessions.

    • http://php.net/manual/en/features.sessions.php

    0 讨论(0)
  • 2021-01-24 15:00

    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.
    0 讨论(0)
提交回复
热议问题