0

So I wrote a program that generates a simple report from a MySQL database. However, after changing the code to accept user input from an HTML form, I suddenly get a variety of errors, all originating from an undefined index (the variables are showing up as null).

The program works perfectly if I don't accept user input through the form.

What I've tried so far...

  1. Switching from POST to GET.
  2. Using an if(isset statement.

Not much, I know, but my knowledge of PHP doesn't go far beyond this.

Here are the specific errors:

"Undefined variable: B_DATE in ... on line 35" and "Undefined variable: E_DATE in ... on line 36"

There are more, but they all originate from the above issue.

Before I post the code, I put a debug array at the beginning of the code and it output the following:

 $debug = true;
 if ($debug === true)
 {
     echo '<hr />
     <h4>Debug Area</h4>
     <pre>';

     print_r(array($_GET, $_POST));

     echo '</pre>
     <hr />';
 }

Debug Area

Array
(
    [0] => Array
        (
            [formID] => IRCcalculatepercentageform
            [B_DATE] => 2014-10-12
            [E_DATE] => 2014-10-13
        )

    [1] => Array
        (
        )

)

and

 if(!isset($_GET['IRCcalculatepercentageform'])){
     echo "No value";
     }

returns "No value".

Here is the code for the HTML form:

 <form method="get" action="IRCcalculatepercentage1.php"> 

 <input type="hidden" name="formID" value="IRCcalculatepercentageform" />

 <p> Type in the date you want to perform your calculation on (year, month, day):    "0000-00-00" </p>
 <p> Beginning Date: <input type="text" name="B_DATE" /></p>
 <p> Ending Date: <input type="text" name="E_DATE" /></p>

 <input type="submit" value="Submit" />
 </form>
 </body>
 </html> 

And here is the program code:

<?php //calculate percentage

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

require_once 'IRCconfig.php';

$connection = 
    new mysqli($db_hostname, $db_username, $db_password, $db_database);

if ($connection->connect_error) die($connection->connect_error);

$B_DATE = $_GET['B_DATE'];
$E_DATE = $_GET['E_DATE'];

/* Computes the number of cells from column 
'C_LAB' that contains the term 'Y'*/

$query1 = "SELECT C_LAB, DATE
           FROM CLIENT_CHECKIN
           WHERE DATE BETWEEN '$B_DATE' AND '$E_DATE'
           HAVING C_LAB = 'Y'";


$result1 = $connection->query($query1);
    if (!$result1) die($connection->error);

$rows1 = $result1->num_rows;

for ($j = 0 ; $j < $rows1 ; ++$j)
{
    $result1->data_seek($j);
    echo 'Computer lab: ' . $result1->fetch_assoc()['C_LAB'] . '<br><br>';
    $count1 = $j;
}

/*Computes the number of cells from column 'C_LAB' 
that contain the term 'N'*/

$query2 = "SELECT C_LAB, DATE
           FROM CLIENT_CHECKIN
           WHERE DATE BETWEEN '$B_DATE' AND '$E_DATE'
           HAVING C_LAB = 'N'";

$result2 = $connection->query($query2);
    if (!$result2) die($connection->error);

$rows2 = $result2->num_rows;

for ($l = 0 ; $l < $rows2 ; ++$l)
{
    $result2->data_seek($l);
    echo 'Computer lab: ' . $result2->fetch_assoc()['C_LAB'] . '<br><br>';
    $count2 = $l;
}

$total = ($count1 + 1) + ($count2 + 1);

echo "The number of clients who used the computer lab is ", $count1 + 1, "<br><br>",
"The total number of clients who did not use the computer lab is ", $count2 + 1, "<br><br>",
"The total number of clients today is ", $total, "<br><br>";

echo "The percentage of clients who used the computer lab today is ", (($count1 + 1) / $total) * 100, 
     "%";

$result1->close();
$connection->close();

?>
dan5ermou5
  • 113
  • 1
  • 1
  • 11
  • `B_DATE` and `E_DATE` are set inside `$_GET` but you are not using `$_GET` when you place them into the SQL. You need to use something like `$B_DATE = $connection->real_escape_string($_GET['B_DATE']);` Otherwise, you are depending on an old deprecated/removed behavior of PHP called `register_globals` wherein variables were auto-created from GET/POST keys – Michael Berkowski Oct 12 '14 at 19:39
  • Please review [How can I prevent SQL injection in PHP](http://stackoverflow.com/questions/60174/how-can-i-prevent-sql-injection-in-php). Now is the time to start learning to use `prepare()/execute()` in MySQLi. – Michael Berkowski Oct 12 '14 at 19:40
  • It's not $_GET['B_DATE'] and $_GET['E_DATE'] but $_GET['B_Date'] and $_GET['E_Date'] – hellcode Oct 12 '14 at 19:51
  • Thanks, I'll check out that post asap. – dan5ermou5 Oct 12 '14 at 19:54
  • Is there any particular reason this is necessary? I've written a couple of other programs that take the same type of input, but only needed an initial statement like this at the beginning: $F_NAME = $_POST['F_NAME']; – dan5ermou5 Oct 12 '14 at 20:02
  • Date is also a reserved word so if your field is called date you might want to surround it with backticks i.e. `date`. –  Oct 12 '14 at 20:03
  • 1
    @jeff *"Date is also a reserved word so if your field is called date you might want to surround it with backticks"* - `date` is not a MySQL reserved word http://dev.mysql.com/doc/refman/5.5/en/reserved-words.html – Funk Forty Niner Oct 12 '14 at 20:53
  • @dan5ermou5 You're using `name="B_Date"` and `name="E_Date"` to go with `$_GET['B_DATE']` and `$_GET['E_DATE']` that is the main reason why your code is failing. Those variables are case-sensitive. Add error reporting to the top of your file(s) right after your opening ` – Funk Forty Niner Oct 12 '14 at 20:55
  • @Fred-ii- OK reserverd word was the incorrect term but the date is still a datatype and should be enclosed in backticks. http://dev.mysql.com/doc/refman/5.6/en/datetime.html –  Oct 13 '14 at 01:40

2 Answers2

2

Change this:

   WHERE DATE BETWEEN '$B_DATE' AND '$E_DATE'

to

   WHERE DATE BETWEEN '".$_GET["B_Date"]."' AND '".$_GET["E_Date"]."'

to let it work. After that take care about security.

hellcode
  • 2,678
  • 1
  • 17
  • 21
  • Awesome, that worked perfectly... I'll start reading up on the security issues now. – dan5ermou5 Oct 12 '14 at 19:56
  • @dan5ermou5 dont edit your question accept the solution. Cause it work. Thanks – arif_suhail_123 Oct 12 '14 at 19:59
  • While I was removing the debug code I deleted the $B_DATE = $_GET['B_DATE']; and $E_DATE = $_GET['E_DATE']; statements at the beginning of the code. Besides editing that back in for clarity everything stayed the same. – dan5ermou5 Oct 12 '14 at 20:37
  • @dan5ermou5 your edit say solved, and you edited you question with his answer. m i missing some thing here. sorry to bother you again and again. Or you probelm still not solved?? – arif_suhail_123 Oct 12 '14 at 20:43
  • Actually, I think I misunderstood you. Yes, I did edit with solved at the beginning. I thought you talking about a different edit. In the future I'll leave my post alone and just say if something worked in the comments. – dan5ermou5 Oct 12 '14 at 20:50
  • @dan5ermou5 it ok dear, if you dont understand, why the solution is not working ask the guy who posted the solution, he or she will explain to you. But if it does work dont forget to say thank you by accepting the right answer. Sorry to bother you that much. – arif_suhail_123 Oct 12 '14 at 21:26
2

As per your originally posted question:

You're using name="B_Date" and name="E_Date" to go with $_GET['B_DATE'] and $_GET['E_DATE'] that is the main reason why your code is failing. Those variables are case-sensitive.

Those need to be changed to:

name="B_DATE" and name="E_DATE"

which is why you are getting an Undefined index... for your variables.

<p> Beginning Date: <input type="text" name="B_Date" /></p>
<p> Ending Date: <input type="text" name="E_Date" /></p>

which needs to be modified to:

<p> Beginning Date: <input type="text" name="B_DATE" /></p>
<p> Ending Date: <input type="text" name="E_DATE" /></p>

Then use isset() for them:

if(isset($_GET["B_DATE"]) && isset($_GET["E_DATE"])) {

$B_DATE = $_GET['B_DATE'];
$E_DATE = $_GET['E_DATE'];

// ...

$query2 = "SELECT C_LAB, DATE
       FROM CLIENT_CHECKIN
       WHERE DATE BETWEEN '$B_DATE' AND '$E_DATE'
       HAVING C_LAB = 'N'";

// rest of your code down to...

$result1->close();
$connection->close();

}

However, using this type of method leaves you open to SQL injection. Use prepared statements, or PDO with prepared statements.


You can also use, and for some protection using mysqli_real_escape_string()

$B_DATE = mysqli_real_escape_string($connection,$_GET['B_DATE']);
$E_DATE = mysqli_real_escape_string($connection,$_GET['E_DATE']);

and:

$query2 = "SELECT C_LAB, DATE 
       FROM CLIENT_CHECKIN 
       WHERE DATE BETWEEN '".$B_DATE."' AND '".$E_DATE."' 
       HAVING C_LAB = 'N'";

Another method using stripslashes() and mysqli_real_escape_string():

$B_DATE = stripslashes($_GET['B_DATE']);
$B_DATE = mysqli_real_escape_string($connection,$_GET['B_DATE']);

$E_DATE = stripslashes($_GET['E_DATE']);
$E_DATE = mysqli_real_escape_string($connection,$_GET['E_DATE']);
Community
  • 1
  • 1
Funk Forty Niner
  • 74,450
  • 15
  • 68
  • 141