1. Advertising
    y u no do it?

    Advertising (learn more)

    Advertise virtually anything here, with CPM banner ads, CPM email ads and CPC contextual links. You can target relevant areas of the site and show ads based on geographical location of the user if you wish.

    Starts at just $1 per CPM or $0.10 per CPC.

Basic question about PHP errors

Discussion in 'PHP' started by HenryCan, May 20, 2017.

  1. #1
    I've just ported a system I wrote a few years back into PHP into a new environment that has PHP 7.1.4 instead of PHP 5.x. My programs used to work perfectly but are now throwing errors, many of which I've never seen before.

    I am not a fluent PHP programmer although I have programmed in a variety of languages, including Java, so I'm not new to programming by any means.

    I was reading a short tutorial about PHP error handling and they suggested writing an error-handling function and invoking it as follows:

        //Error handler function
        function customError($errno, $errstr, $errfile, $errline, $errcontext) {
              echo "<b>Error:</b> [$errno] $errstr<br>";
              echo "<b>File/Line:</b> $errfile/$errline<br>";
              //echo "<b>Error context:</b><br>";
              //print_r($errcontext);
              echo "....Ending Program";
              die();
            }
    
        //Set error handler
        set_error_handler("customError",E_ALL);
    
    
    PHP:
    I did that and got this:

    Error: [8] Undefined index: report_layout
    File/Line: /storage/h13/139/1556139/public_html/SideTrekkedContributions.php/28
    Code (markup):
    In the first line of that, am I correct in assuming that the [8] denotes the severity level of the error, specifically E_NOTICE, which is defined as "Run-time notices. The script found something that might be an error, but could also happen when running a script normally."? Or is the 8 uniquely associated with an "Undefined index" error in a world where every distinct error has a specific number associated with it, like 37 for division by zero and 412 for array index out of bounds? I think it must be the former and that there will be all kinds of errors that have the number 8 but my knowledge of PHP is sketchy so I want to be sure.

    Now, assuming I'm right and that 8 is the severity of the error, what should one normally do with E_NOTICE errors? Ideally, I'd like PHP not to display this message and I'd like to get rid of the message by doing whatever I need to do to prevent PHP from thinking there's anything wrong (as opposed to telling it not to show me errors below a certain severity). In this particular case, the line of code identified as the source of the error is this:
    switch($_POST['report_layout']) {
    PHP:
    I'm darned if I can see what's wrong with this. I never got an error of any kind about this code on the old system. But maybe the old system wanted to show me messages like this but had minor errors suppressed; I really don't know. I tried initializing that variable to null
    $report_layout = null;
    PHP:
    but that did NOT keep the error from appearing. I'm at a loss how to satisfy PHP that the variable has been appropriately initialized so it doesn't have to tell me that there's an undefined index.

    Can anyone enlighten me on the points I've raised?
     
    HenryCan, May 20, 2017 IP
  2. sarahk

    sarahk iTamer Staff

    Messages:
    28,494
    Likes Received:
    4,457
    Best Answers:
    123
    Trophy Points:
    665
    #2
    Here's your list of error numbers: http://php.net/manual/en/errorfunc.constants.php
    [8] looks like it's a pretty generic "oops" type of result - not the severity though.

    Lots of people suppress error messages and do nothing about them. I'd recommend digging through your script and identifying them as you could have functions that no longer exist and will stop your script from functionining.
     
    sarahk, May 20, 2017 IP
  3. akhileshbc

    akhileshbc Active Member

    Messages:
    98
    Likes Received:
    1
    Best Answers:
    5
    Trophy Points:
    75
    #3
    sarahk has already answered your other questions.

    Let me answer your last question.

    The error that you are getting clearly mentions this:
    Undefined index: report_layout

    Which means that the associative array $_POST, is not having an element with the key named as report_layout

    So, what you can do is, add an IF condition before that SWITCH, to check whether the array key exists!

    Example:
    if( isset( $_POST['report_layout'] ) )
    {
        switch($_POST['report_layout'])
        {
            //......
            //......
        }
    }
    PHP:
    Hope this helps.

    Thank you
     
    akhileshbc, May 20, 2017 IP
  4. HenryCan

    HenryCan Member

    Messages:
    39
    Likes Received:
    1
    Best Answers:
    0
    Trophy Points:
    43
    #4
    Thanks, Sarahk, I was pretty sure that the number 8 was the severity of the error and you've now confirmed that.

    As for your general point, I totally agree. I need to go through my code and improve it to prevent any of the errors from appearing in the first place. I need to get up to speed on "best practices" for PHP. I'll likely be posting specific questions as I come to problem areas and getting the advice of the experts here.

    I realize now why I'm seeing more PHP messages than I'm used to seeing: there was a line in my .htaccess file that the hosting service put in there automatically. They even warn you not to change it:
    # HTID:1177512: DO NOT REMOVE OR MODIFY THIS LINE AND THE LINES BELOW
    php_value display_errors 1
    # DO NOT REMOVE OR MODIFY THIS LINE AND THE LINES ABOVE HTID:1177512:
    
    Code (markup):
    When I changed the 1 to a 0 and ran my code again, all the messages from PHP disappeared. I strongly suspect that they never used to force the display of errors on the old system but are forcing it on the new one, thus accounting for my sudden increase in messages.

    Naturally, this just emphasizes the need for me to improve this code so PHP doesn't even *want* to complain :)

    By the way, thanks for your prompt reply! (I'm afraid I've been side-tracked with other issues and didn't get back here until just now.)
     
    Last edited: May 22, 2017
    HenryCan, May 22, 2017 IP
  5. HenryCan

    HenryCan Member

    Messages:
    39
    Likes Received:
    1
    Best Answers:
    0
    Trophy Points:
    43
    #5
    I pretty much figured that's what was going on. The thing is that report_layout *is* defined before I get to that line of code so I'm not sure why the PHP interpreter is concluding otherwise.

    Here's my full code for SideTrekkedContributions.php:
    <!--#include file="fragments/#alfa.shtml"-->
    <?php include('fragments/_getThemes.php'); ?>
    </head>
    <body>
    
        <?php
           
        //Display the menu that lets the user decide which report they want
        include ('fragments/_SideTrekkedContributionsMenu.shtml');
       
        //Execute the program that displays the desired report.
        switch($_POST['report_layout']) {
            case 'Format1':
                include('SideTrekkedContributions1.php');
                break;
            case 'Format2':
                include('SideTrekkedContributions2.php');
                break;
            case 'Format3':
                include('SideTrekkedContributions3.php');
                break;
        }
       
        ?>
       
    </body>
    </html>
    PHP:
    And here's my code for _SideTrekkedContributionsMenu.shtml:
    <h2>SideTrekked Contributions</h2>
    
    <form method="post" action="<?php echo $_SERVER['PHP_SELF']; ?>">
    <p>You can choose from multiple layouts for the report. Please select the one you prefer, then press the Display Report button. To restore the form to its original appearance without submitting it, press the Reset button.</p>
    
    <fieldset><legend>Report Layout</legend>
    <input type="radio" name="report_layout" value="Format1"/>In publication order<br/>
    <input type="radio" name="report_layout" value="Format2"/>In order by title<br/>
    <input type="radio" name="report_layout" value="Format3"/>In order by contributor last name<br/>
    </fieldset>
    
    <p><input name="submitForm" id="submitForm" type="submit" value="Display Report" />
    <input name="reset" id="reset" type="reset" value="Reset" /></p>
    
    <p><em>It may take a few seconds after you click the Display Report button to gather and format all the data. Please be patient.</em></p>
    </form>
    
    HTML:
    Given that _SideTrekkedContributionsMenu.shtml is imbedded into the code before PHP executes the switch statement, I *think* report_layout is already defined. What am I missing? What do I need to do so that PHP doesn't think report_layout is undefined?
     
    HenryCan, May 22, 2017 IP
  6. sarahk

    sarahk iTamer Staff

    Messages:
    28,494
    Likes Received:
    4,457
    Best Answers:
    123
    Trophy Points:
    665
    #6
    I'd start by just doing a var_dump of $_POST before you do the switch to be sure - it could be that no value was selected and therefore the variable doesn't appear in $_POST. To get around that you need to either give report_layout a default value so that a radio button is preselected or you need to add array_key_exists before your switch.
     
    sarahk, May 22, 2017 IP
  7. HenryCan

    HenryCan Member

    Messages:
    39
    Likes Received:
    1
    Best Answers:
    0
    Trophy Points:
    43
    #7
    I suppose I could force report_layout to have a value and simply let the user change that value if they didn't like the default. I'd rather not though so I think I will try the array_key_exists function. I've never come across that one before but it would let me write an if that says "if report_layout has a value, run the appropriate report, otherwise, just display the menu and await input". Apparently, the switch is being executed before the user has even chosen a report, thus prompting the complaint about the index not being defined.

    Thanks for the insight!
     
    HenryCan, May 23, 2017 IP
  8. Blank ™

    Blank ™ Well-Known Member

    Messages:
    223
    Likes Received:
    18
    Best Answers:
    6
    Trophy Points:
    110
    #8
    Having a default value for a multi-option selection is a must (unless we are talking about surveys and such), not a workaround. Just add DEFAULT to one of the options that you think most users would want to choose.,
     
    Blank ™, May 23, 2017 IP
  9. PoPSiCLe

    PoPSiCLe Illustrious Member

    Messages:
    4,623
    Likes Received:
    725
    Best Answers:
    152
    Trophy Points:
    470
    #9
    Just to clarify a little bit. $_POST-values are ONLY present after a form has been submitted (a form with method="post", that is). So the form you include does not mean the $_POST['report_layout'] is defined. Nor does it mean it will be defined even if you set a default value in the form (you will have to set that in the PHP directly).

    A normal way to do this would be to check to see if the $_POST-value is empty, for instance like this:
    
    if (isset($_POST['submitForm'])) {
      //do the rest of the $_POST-processing here
    }
    
    PHP:
    Granted, this wouldn't actually check to see if there is a $_POST['report_layout'] actually set - but then again, that would be something to check like this, for instance:
    
    if (isset($_POST['submitForm'])) {
     if (isset($_POST['report_layout'])) {
       switch($_POST['report_layout']) {
        case 'Format1':
        include('SideTrekkedContributions1.php');
        break;
        case 'Format2':
        include('SideTrekkedContributions2.php');
        break;
        case 'Format3':
        include('SideTrekkedContributions3.php');
        break;
       }
     }
    }
    
    PHP:
    That will first check to see if the form has been submitted, then check if the $_POST['report_layout'] is set. Normally you would add some error-checking, so if it is not filled out, you will present the user with an error-message explaining what needs to be done.

    Also, I see you're using .shtml-files - why? And your naming conventions... you are mixing camelCase (with wrong formatting - camelCase starts with a lower-case letter) with underscore naming, and you have extremely complicated names for quite a bit of code... also, the first comment doesn't seem to match the code presented, and so on.
     
    PoPSiCLe, May 23, 2017 IP
  10. Blank ™

    Blank ™ Well-Known Member

    Messages:
    223
    Likes Received:
    18
    Best Answers:
    6
    Trophy Points:
    110
    #10
    As long as the end user is not playing with the code, it should. :)

    Second point, I've no idea why do you need two isset there - you're looking for one specific object there, not two or more.

    
    if (isset($_POST["report_layout"]) 
    {
        switch ($_POST["report_layout"]) 
        {
           case "Option 1":
                // Do something here related to Option 1;
              break;
           case "Option 2":
                // Do something here related to Option 2;
             break;
           case "Option 3":
                // Do something here related to Option 3;
              break;
           case "Option 4":
                // Do something here related to Option 4;
             break;
           case "Option 1":
                // Do something here related to Option 1;
             break;
           default:
                // None of the option values have been found. Throw an error?
        }
    }
    
    PHP:
     
    Blank ™, May 23, 2017 IP
  11. sarahk

    sarahk iTamer Staff

    Messages:
    28,494
    Likes Received:
    4,457
    Best Answers:
    123
    Trophy Points:
    665
    #11
    Much of this debate comes down to the old idea that you should never actually use the $_POST or $_GET values directly.

    Your values should be moved into variables, sanitized, defaults checked and then used.

    The PHP code that does the logical work should also be before the <head> tag with only display variables being worked lower down. Following that then leads you into just doing MVC which can be done on even the smallest "from scratch" site - but all of that is well outside the scope of the OP's question.
     
    sarahk, May 23, 2017 IP
  12. PoPSiCLe

    PoPSiCLe Illustrious Member

    Messages:
    4,623
    Likes Received:
    725
    Best Answers:
    152
    Trophy Points:
    470
    #12
    Granted, in this specific instance, checking for one isset() is enough. Most forms, however, will have more than one input, and hence, checking to see if the form is actually submitted before doing anything else, is usually good practice.
     
    PoPSiCLe, May 24, 2017 IP
  13. GameO.Over

    GameO.Over Active Member

    Messages:
    45
    Likes Received:
    7
    Best Answers:
    1
    Trophy Points:
    65
    #13
    As a general rule, you should never assume something is set.

    A simple ternary will do the job

    isset($_POST['index']) ? $_POST['index''] : ''
    PHP:
    Also no need to nest if statements. Following my rule of never assuming something is set I would always check that the form has been properly submitting before checking for anything else.

    if (isset($_POST['submit']) && isset($_POST['index'])) {
     
    }
    
    if (isset($_POST['submit'], $_POST['index'])) {
     
    }
    PHP:
    A simple
    var_dump($_POST);
    PHP:
    after submit will show you what is being set, if nothing, then you need to double check you're actually doing a post request you can do
    var_dump($_SERVER["REQUEST_METHOD"]);
    PHP:
     
    Last edited: May 24, 2017
    GameO.Over, May 24, 2017 IP
  14. PoPSiCLe

    PoPSiCLe Illustrious Member

    Messages:
    4,623
    Likes Received:
    725
    Best Answers:
    152
    Trophy Points:
    470
    #14
    If you're using modern PHP, you can just do:
    
    $index = $_POST['index'] ?? '';
    
    PHP:
    No need to use isset() or anything - if the index is set, it will exist, and be used, if not, empty.
     
    PoPSiCLe, May 25, 2017 IP
  15. HenryCan

    HenryCan Member

    Messages:
    39
    Likes Received:
    1
    Best Answers:
    0
    Trophy Points:
    43
    #15
    Sorry for the delay in responding; I've been playing with my PHP code learning things by trial and error when I couldn't find them in the manual.

    You've raised some excellent points. I had only a bare working knowledge of PHP when I first wrote this code 4 or 5 years and haven't touched it since so I'd forgotten a bunch of things including the fact that report_layout wouldn't have a value if none of the report types were chosen on the form; for some reason, I thought it always had some kind of value, even if it was just blank or null. That is why I was perplexed about the error I was getting. Once I remembered that $_POST only contains values that were selected or typed by the user, I rewrote the code to check everything that came back in $_POST and to put it in its own work variable; if any given value wasn't in $_POST, I set an arbitrary value.

    I tested via array_key_exists(). For example:
                (array_key_exists('proposer', $_POST)) ? $proposer = trim($_POST['proposer']) : $proposer = ""; //This is the Proposer text field.
    
    PHP:
    Is there any reason why that is better or worse than isset() (or any of the other possible approaches)?

    I also hadn't realized that the switch statement would be executed immediately after the form had been shown the user, before he/she had had a chance to choose a report format. I simply put an if around the whole switch statement so it wouldn't be executed until report_layout had a value, which would only happen after pressing Submit:

        //If the user has selected a report, execute the program that displays the desired report.
        if (array_key_exists('report_layout', $_POST)) {
        switch($_POST['report_layout']) {
            case 'Format1':
                include('SideTrekkedContributions1.php');
                break;
            case 'Format2':
                include('SideTrekkedContributions2.php');
                break;
            case 'Format3':
                include('SideTrekkedContributions3.php');
                break;
        } //end switch
        } //end if
    
    PHP:
    Would you agree that this is a reasonable way to handle things or could I be doing better?
     
    HenryCan, May 29, 2017 IP
  16. sarahk

    sarahk iTamer Staff

    Messages:
    28,494
    Likes Received:
    4,457
    Best Answers:
    123
    Trophy Points:
    665
    #16
    That all looks good. The only thing I'd change is

    $prosper = (array_key_exists('proposer', $_POST)) ? trim($_POST['proposer']) : "";
    PHP:
    But there's also @PoPSiCLe's way which I haven't yet tried

    $prosper = $_POST['prosper'] ?? '';
    PHP:
     
    sarahk, May 29, 2017 IP
  17. GameO.Over

    GameO.Over Active Member

    Messages:
    45
    Likes Received:
    7
    Best Answers:
    1
    Trophy Points:
    65
    #17
    AKE only checks if a key exists and doesn't care about the value, where as isset will return false if it exists but is a null value... so in this case you are fine to use AKE.
     
    GameO.Over, May 29, 2017 IP
  18. PoPSiCLe

    PoPSiCLe Illustrious Member

    Messages:
    4,623
    Likes Received:
    725
    Best Answers:
    152
    Trophy Points:
    470
    #18
    And I would say that the new PHP 7-way is cleaner all around. But yes, the method you're using is perfectly fine.
     
    PoPSiCLe, May 29, 2017 IP
  19. Harshal shah

    Harshal shah Active Member

    Messages:
    126
    Likes Received:
    5
    Best Answers:
    1
    Trophy Points:
    65
    #19
    This is small program done using your error handler and it's working fine.
    <?php
    // error handler function
    function myErrorHandler($errno, $errstr, $errfile, $errline)
    {
        echo "<b>Error:</b> [$errno] $errstr<br>";
              echo "<b>File/Line:</b> $errfile/$errline<br>";
              
              echo "....Ending Program";
              die();
    }
    // function to test the error handling
    function scale_by_log($vect, $scale)
    {
        if (!is_numeric($scale) || $scale <= 0) {
            trigger_error("log(x) for x <= 0 is undefined, you used: scale = $scale", E_USER_ERROR);
        }
        if (!is_array($vect)) {
            trigger_error("Incorrect input vector, array of values expected", E_USER_WARNING);
            return null;
        }
        $temp = array();
        foreach($vect as $pos => $value) {
            if (!is_numeric($value)) {
                trigger_error("Value at position $pos is not a number, using 0 (zero)", E_USER_NOTICE);
                $value = 0;
            }
            $temp[$pos] = log($scale) * $value;
        }
        return $temp;
    }
    // set to the user defined error handler
    $old_error_handler = set_error_handler("myErrorHandler");
    // trigger some errors, first define a mixed array with a non-numeric item
    echo "vector a\n";
    $a = array(2, 3, "foo", 5.5, 43.3, 21.11);
    print_r($a);
    // now generate second array
    echo "----\nvector b - a notice (b = log(PI) * a)\n";
    /* Value at position $pos is not a number, using 0 (zero) */
    $b = scale_by_log($a, M_PI);
    print_r($b);
    // this is trouble, we pass a string instead of an array
    echo "----\nvector c - a warning\n";
    /* Incorrect input vector, array of values expected */
    $c = scale_by_log("not array", 2.3);
    var_dump($c); // NULL
    // this is a critical error, log of zero or negative number is undefined
    echo "----\nvector d - fatal error\n";
    /* log(x) for x <= 0 is undefined, you used: scale = $scale" */
    $d = scale_by_log($a, -2.5);
    var_dump($d); // Never reached
    ?>
    
    Code (markup):

    OUTPUT :



    vector a Array ( [0] => 2 [1] => 3 [2] => foo [3] => 5.5 [4] => 43.3 [5] => 21.11 ) ---- vector b - a notice (b = log(PI) * a) Error: [1024] Value at position 2 is not a number, using 0 (zero)

    File/Line: /opt/lampp/htdocs/Jagdish/test/cutom_error_handler.php/27

    ....Ending Program
     
    Harshal shah, May 31, 2017 IP