Richland College Multimedia Learning Center

Digital Media Programming with PHP and MySQL

Digital Media Programming with PHP and MySQL

Changing a Database's Contents with PHP

Database Error Messages

As you work with databases and PHP, you might occasionally encounter some error messages related to the database itself. Following are some of the messages that you might need to debug:

Datasource Not Found

Wrong Number of Parameters

Base Table Not Found

Invalid Use of Is Operator


The Checkbook Application

Now let's look at the code for the fake Checkbook application. These pages are running on the jimlink.net server and are using a mysqli() database object in each page that accesses the MySQL database.

(You will need a username and password to log in. Use the fake username of "harry" (without the quotes) and the fake password of "potter" (also without the quotes).

You can see the fake checkbook running with a mysqli() object here.

The main display page is checkbook.php:

<?php
  require_once "config.php";
  require "loginAndLogout.php";
  
  $dbobject = new mysqli(DBSERVER, DBUSER, DBPWD, DBNAME);
  /* check connection */
  $db_error = $dbobject->connect_errno;
  if ($db_error)
  {
      printf("<p>Connect failed: %s</p>\n", $db_error);
      exit();
  }
  
?>

<!DOCTYPE html>
<html>
<head>
  <meta charset="UTF-8">
  <title>Home Checkbook</title>
  <link rel="stylesheet" type="text/css" href="checkbook.css" />
  <script type="text/javascript" src="includes/jquery.js"></script>
  <script type="text/javascript">
    $(document).ready(function(){
      $(':submit').css("cursor", "pointer");
    });

    function logoff()
    {
      var returnValue = confirm("Do you really want to log off?");
      if (returnValue == true)
      {
        document.getElementById("autoLogoff").value = "1";
        return true;
      }
      else
      {
        return false;
      }
    }
  </script>
</head>
<body>
  <div id="checkDiv">
    <h1>Home Checkbook</h1>
    <br />
    <form action="addtrans.php" id="addtransForm" name="addtransForm" method="post">
      <input type="submit" value="Add a Transaction">
    </form>
    <form action="loginAndLogout.php" id="logoutForm" name="logoutForm" class="extraLeftSpace" method="post"
          onsubmit="return logoff();">
      <input type="hidden" name="autoLogoff" id="autoLogoff" value="0">
      <input type="submit" value="Log off">
    </form>
    <br />
    <br />
    <table id="mainTable">
      <tr>
        <th>  Date</th>
        <th>  Amount</th>
        <th>  Description</th>
        <th>   </th>
        <th>   </th>
      </tr>
    <?php
      $querystr = "SELECT * FROM Transaction ORDER BY TransDate DESC, Description";
      $recordset = $dbobject->query($querystr);

      $row = $recordset->fetch_assoc();
      while ($row !== null)
      {
        $rowId = $row["ID"];
        $transDate = $row["TransDate"];
        $amount = $row["Amount"];
        $descr = $row["Description"];

        printf('<tr>
                  <td class="numeric">%s</td>
                  <td class="numeric">$%01.2f</td>
                  <td>%s</td>
                  <td>
                    <form action="edittrans.php" method="post">
                      <input type="hidden" name="rowID" value="%d" />
                      <input type="submit" value="Edit" />
                    </form>
                  </td>
                  <td>
                    <form action="deletetrans.php" method="post">
                      <input type="hidden" name="rowID" value="%d" />
                      <input type="submit" value="Delete" />
                    </form>
                  </td>
                </tr>',
          date("m/d/Y", strtotime($transDate)),
          $amount,
          $descr,
          $rowId,
          $rowId);
        $row = $recordset->fetch_assoc();
      }  //end while()
    ?>
      </table>
  <br />
  <form action="addtrans.php" id="addtransForm" name="addtransForm" method="post">
    <input type="submit" value="Add a Transaction">
  </form>
  <br />
  </div>
</body>
</html>

Please note these points about the mysqli portions of the above code:


Add

When you click the "Add a Transaction" button on the main fake checkbook page (see below), the page that displays is addtrans.php:

<?php
  require "loginAndLogout.php";
  require_once "config.php";

  $datestamp = date("m/d/Y");
?>
<!DOCTYPE html>
<html>
<head>
  <meta charset="UTF-8">
  <title>Add a Transaction</title>
  <link rel="stylesheet" type="text/css" href="checkbook.css" />
  <script type="text/javascript" src="includes/jquery.js"></script>
  <script type="text/javascript">
    $(document).ready(function(){
      $(':submit').css("cursor", "pointer");
    });
  </script>
  <script type="text/javascript">
    function setInitialFocus()
    {
      document.addform.Amount.focus();
    }

    function verifyfields()
    {
      var retValue = true;
      var retMsg = "";
      if (document.addform.TransDate.value == "")
      {
        retMsg += "\nEnter a date.";
        retValue = false;
      }
      if (document.addform.Amount.value == "")
      {
        retMsg += "\nEnter an amount.";
        retValue = false;
      }
      else if (isNaN(parseFloat(document.addform.Amount.value)))
      {
        retMsg += "\nMake sure the amount has only numeric characters (and a period) in it.";
        retValue = false;
      }
      if (document.addform.Description.value == "")
      {
        retMsg += "\nEnter a description.";
        retValue = false;
      }
      if (retMsg !== "")
      {
        alert(retMsg);
        document.getElementById("Amount").focus();
      }
      return retValue;
    }
  </script>
</head>
<body onload="setInitialFocus();">
  <div id="checkDiv">
    <h1>Add a Transaction</h1>
    <br />
    <a href="checkbook.php">Home/Back</a>
    <br />
    <br />
    <form action="addnewtrans.php" method="post" name="addform" onsubmit="return verifyfields();">
      <table id="transTable">
        <tr>
          <td>Date: </td>
          <td>
          <input type="text" name="TransDate" value="<?php echo $datestamp; ?>" /></td>
        </tr>
        <tr>
          <td>Amount: </td>
          <td>
          <input type="text" name="Amount" id="Amount" /></td>
        </tr>
        <tr>
          <td>Description: </td>
          <td>
          <input type="text" name="Description" /></td>
        </tr>
        <tr>
          <td colspan="2" align="center">
          <input type="submit" value="Add the transaction" /></td>
        </tr>
      </table>
    </form><br /><br /><a href="checkbook.php">Home/Back</a>
  </div>
</body>
</html>

Here is the SQL Insert page, addnewtrans.php:

<?php
  require "loginAndLogout.php";
  require_once "config.php";
  $dbobject = new mysqli(DBSERVER, DBUSER, DBPWD, DBNAME);
  /* check connection */
  $db_error = $dbobject->connect_errno;
  if ($db_error)
  {
      printf("<p>Connect failed: %s</p>\n", $db_error);
      exit();
  }
  try
  {
    error_reporting (E_ALL);
    
    require("includes/isSQLInject.php");
    require("includes/CheckURLandFORMscope.php");
    
    $descr = htmlspecialchars($_POST["Description"]);
    $amt = htmlspecialchars($_POST["Amount"]);
    $transdate = date_format(date_create(htmlspecialchars($_POST["TransDate"])),"Y-m-d");
    $tz = new DateTimeZone('America/Chicago'); // or whatever zone you're after
    $dt = new DateTime("now", $tz);
    $datetimestamp = $dt->format('Y-m-d H:i:s');

    $querystr = sprintf("Insert Into Transaction
                      (Description, Amount, TransDate, TimeStamp)
                      Values
                      ('%.40s', %f, '%s', '%s')",
                      $dbobject->real_escape_string($descr),
                      $amt,
                      $transdate,
                      $datetimestamp);
    $result = $dbobject->query($querystr);
    if ($result === false)
    {
      throw new Exception("Database insert failed.");
    }
    $filename = "checkbook.php";
    if (strpos($_SERVER['SERVER_NAME'],'localhost') === false)
    {
      header("Location: " . constant("SECUREURL") . "/PHPStuff/" . $filename);
      exit();
    } else {
      header("Location: " . constant("LOCALURL") . "/PHPStuff/" . $filename);
      exit();
    }
  }
  catch (Exception $e)
  {
    echo "The site has experienced a serious error.<br /><br />";
    echo "Please call the site administrator at <strong>1-800-333-3333</strong>,<br />";
    echo "or send e-mail to <strong>support@mysite.edu</strong>, and give them this information:<br /><br />";
    echo $e->getMessage(), "<br />";
  }
?>

Please note these points about the above code:


Formatting Codes in the printf( ) Family of PHP Functions

The formatting codes such as %s and %f in the code above, are special place-holding characters which tell printf( ) and sprintf( ) what kind of information to put into the formatted string at the place where the formatting code is.

The three most commonly-used formatting codes are these:

When you use these formatting codes in the creation of a SQL query string, you must keep in mind these points about how SQL expects to see certain data types in the query. These points are also noted above, but need to be repeated here:

If you want to see the complete list of formatting codes, there is a list on the reference page for sprintf( ) at php.net.


Edit/Update

If you click the "Edit" button, the first page that displays is edittrans.php:

<?php
  require "loginAndLogout.php";
  require_once "config.php";
  
  $dbobject = new mysqli(DBSERVER, DBUSER, DBPWD, DBNAME);
  /* check connection */
  $db_error = $dbobject->connect_errno;
  if ($db_error)
  {
      printf("<p>Connect failed: %s</p>\n", $db_error);
      exit();
  }
  
  error_reporting (E_ALL);
  
  $rowId = $_REQUEST["rowID"];
  $querystr = sprintf("SELECT * FROM Transaction Where ID = %d", $rowId);

  $resultset = $dbobject->query($querystr);
  $myrow = $resultset->fetch_assoc();
  $rowId = $myrow["ID"];
  $transDate = $myrow["TransDate"];
  $amount = $myrow["Amount"];
  $descr = $myrow["Description"];
?>
<!DOCTYPE html>
<html>
<head>
  <meta charset="UTF-8">
  <title>Update a Transaction</title>
  <script type="text/javascript" src="includes/jquery.js"></script>
  <script type="text/javascript">
    $(document).ready(function(){
      $(':submit').css("cursor", "pointer");
    });
  </script>
  <script type="text/javascript">
    function checkedits()
    {
      var retValue = true;
      var retMsg = "";
      if (document.editform.TransDate.value == "")
      {
        retMsg += "\nEnter a date.";
        retValue = false;
      }
      if (document.editform.Amount.value == "")
      {
        retMsg += "\nEnter an amount.";
        retValue = false;
      }
      else if (isNaN(parseFloat(document.editform.Amount.value)))
      {
        retMsg += "\nMake sure the amount has only numeric characters (and a period) in it.";
        retValue = false;
      }
      if (document.editform.Description.value == "")
      {
        retMsg += "\nEnter a description.";
        retValue = false;
      }
      if (retMsg !== "")
      {
        alert(retMsg);
        document.getElementById("Amount").focus();
      }
      return retValue;
    }
  </script>
  <link rel="stylesheet" type="text/css" href="checkbook.css" />
</head>
<body>
  <div id="checkDiv">
    <h1>Update a Transaction</h1>
    <br>

    <a href="checkbook.php">Home/Back</a>
    <br>
    <br>
      <form action="updatetrans.php" name="editform" method="post" onsubmit="return checkedits();">
        <table id="transTable">
            <tr>
              <td>Date: </td>
              <td>
              <input type="hidden" name="ID" value="<?php echo $rowId;?>" />
              <input type="text" name="TransDate" value="<?php print(date("m/d/Y", strtotime($transDate)));?>" /></td>
            </tr>
            <tr>
              <td>Amount: </td>
              <td>
              <input type="text" name="Amount" id="Amount" value="<?php printf('%01.2f',$amount);?>" /></td>
            </tr>
            <tr>
              <td>Description: </td>
              <td>
              <input type="text" name="Description" value="<?php echo $descr;?>" /></td>
            </tr>
            <tr>
              <td colspan="2" align="center">
                <input type="submit" value="Update" />
              </td>
            </tr>
        </table>
      </form>
      <br>
      <br>
      <a href="checkbook.php">Home/Back</a>
  </div>
</body>
</html>

When a transaction is edited, the "Update" submit button sends the form data to page updatetrans.php:

<?php
  require "loginAndLogout.php";
  require_once "config.php";
    
  $dbobject = new mysqli(DBSERVER, DBUSER, DBPWD, DBNAME);
  /* check connection */
  $db_error = $dbobject->connect_errno;
  if ($db_error)
  {
      printf("<p>Connect failed: %s</p>\n", $db_error);
      exit();
  }
  try
  {
    error_reporting (E_ALL);
    
    require("includes/isSQLInject.php");
    require("includes/CheckURLandFORMscope.php");

    $rowId = htmlspecialchars($_POST["ID"]);
    $descr = htmlspecialchars($_POST["Description"]);
    $amt = htmlspecialchars($_POST["Amount"]);
    $transdate = date_format(date_create(htmlspecialchars($_POST["TransDate"])),"Y-m-d");
    $tz = new DateTimeZone('America/Chicago'); // or whatever zone you're after
    $dt = new DateTime("now", $tz);
    $datetimestamp = $dt->format('Y-m-d H:i:s');
    

    $querystr = sprintf("Update Transaction Set 
                           Description = '%.40s',
                           Amount = %f,
                           TransDate = '%s',
                           TimeStamp = '%s'
                        Where ID = %d",
                        $dbobject->real_escape_string($descr),
                        $amt,
                        $transdate,
                        $datetimestamp,
                        $rowId);
    $result = $dbobject->query($querystr);

    if ($result === false)
    {
      throw new Exception("Database update failed.");
    }
    $filename = "checkbook.php";
    if (strpos($_SERVER['SERVER_NAME'],'localhost') === false)
    {
      header("Location: " . constant("SECUREURL") . "/PHPStuff/" . $filename);
      exit();
    } else {
      header("Location: " . constant("LOCALURL") . "/PHPStuff/" . $filename);
      exit();
    }
  }
  catch (Exception $e)
  {
    echo "The site has experienced a serious error.<br /><br />";
    echo "Please call the site administrator at <strong>1-800-333-3333</strong>,<br />";
    echo "or send e-mail to <strong>support@mysite.edu</strong>, and give them this information:<br /><br />";
    echo $e->getMessage(), "<br />";
  }
?>

Delete

Please recall that one of my main "Rules of Survival" in the world of databases is Before you do a SQL Delete, do a SQL Select.

In keeping with that philosophy, if you click the "Delete..." button, the first page that displays is deletetrans.php, which does a SELECT query on the transaction being considered, and displays that transaction's information to the user.

<?php
  require "loginAndLogout.php";
  require_once "config.php";
  
  $dbobject = new mysqli(DBSERVER, DBUSER, DBPWD, DBNAME);
  /* check connection */
  $db_error = $dbobject->connect_errno;
  if ($db_error)
  {
      printf("<p>Connect failed: %s</p>\n", $db_error);
      exit();
  }
  
  error_reporting (E_ALL);
  
  $rowId = $_REQUEST["rowID"];
  $querystr = sprintf("SELECT * FROM Transaction Where ID = %d", $rowId);

  $resultset = $dbobject->query ($querystr);
  if ($resultset !== false)
  {
    $myrow = $resultset->fetch_assoc();
    $rowId = $myrow["ID"];
    $transDate = $myrow["TransDate"];
    $amount = $myrow["Amount"];
    $descr = $myrow["Description"];
  }
  
?>
<!DOCTYPE html>
<html>
<head>
  <meta charset="UTF-8">
  <title>Delete a Transaction</title>
  <link rel="stylesheet" type="text/css" href="checkbook.css" />
  <script type="text/javascript" src="includes/jquery.js"></script>
  <script type="text/javascript">
    $(document).ready(function(){
      $(':submit').css("cursor", "pointer");
    });
  </script>
</head>
<body>
  <div id="checkDiv">
    <h1>Delete a Transaction</h1>
    <br />

    <a href="checkbook.php">Oops, Keep this Record, and go Back/Home!</a>
    <br />
    <br />
      <form action="deltrans.php" name="deleteform" method="post">
        <table id="transTable">
            <tr>
              <td>Date: </td>
              <td>
                <input type="hidden" name="ID" value="<?php echo $rowId;?>" />
                <strong><?php print(date("m/d/Y", strtotime($transDate)));?></strong>
              </td>
            </tr>
            <tr>
              <td>Amount: </td>
              <td>
                <strong><?php printf('%01.2f',$amount);?></strong>
              </td>
            </tr>
            <tr>
              <td>Description: </td>
              <td>
                <strong><?php echo $descr;?></strong>
              </td>
            </tr>
            <tr>
              <td colspan="2" align="center">
                <input type="submit" value="Delete" />
              </td>
            </tr>
        </table>
      </form>
      <br />
      <br />
      <a href="checkbook.php">Oops, Keep this Record, and go Back/Home!</a>
  </div>
</body>
</html>

If you click the "Delete the Record" submit button, the form data is sent to page deltrans.php:

<?php
  require "loginAndLogout.php";
  require_once "config.php";
  
  $dbobject = new mysqli(DBSERVER, DBUSER, DBPWD, DBNAME);
  /* check connection */
  $db_error = $dbobject->connect_errno;
  if ($db_error)
  {
      printf("<p>Connect failed: %s</p>\n", $db_error);
      exit();
  }
  try
  {
    error_reporting (E_ALL);

    require("includes/isSQLInject.php");
    require("includes/CheckURLandFORMscope.php");

    $rowId = $_POST["ID"];

    $querystr = sprintf("Delete from Transaction
                          Where ID = %d",
                          $rowId);

    $result = $dbobject->query($querystr);

    if ($result === false)
    {
      throw new Exception("Database delete failed.");
    }
    $filename = "checkbook.php";
    if (strpos($_SERVER['SERVER_NAME'],'localhost') === false)
    {
      header("Location: " . constant("SECUREURL") . "/PHPStuff/" . $filename);
      exit();
    } else {
      header("Location: " . constant("LOCALURL") . "/PHPStuff/" . $filename);
      exit();
    }
  }
  catch (Exception $e)
  {
    echo "The site has experienced a serious error.<br /><br />";
    echo "Please call the site administrator at <strong>1-800-333-3333</strong>,<br />";
    echo "or send e-mail to <strong>support@mysite.edu</strong>, and give them this information:<br /><br />";
    echo $e->getMessage(), "<br />";
  }
?>

The Login Pages

The pages which are used by the fake checkbook pages to require the user to log in, are listed below.

The form page is loginform.php:

<?php
  session_start();
?>
<!DOCTYPE html>
<html lang="en">
<head>
  <meta http-equiv="content-type" content="text/html; charset=utf-8" />
  <title>Fake Checkbook</title>
  <link rel="stylesheet" type="text/css" href="PHPstyles.css" />
  <script type="text/javascript">
    function positionCursor()
    {
      document.getElementById("username").focus();
    }
  </script>
</head>

<body onload="positionCursor();">
<div id="mainDiv">
    <h4 class="centered">Log In</h4>
    <?php
      if (!empty($_SESSION['error_message'])) {
        echo "<h3 class='ErrorMsg'>" . $_SESSION['error_message'] . "</h3>";
        unset($_SESSION['error_message']);
      } else {
        echo "<h3> </h3>";
      }
    ?>
    <form action="actionLogin.php" method="Post">
      <table>
        <tr>
          <td>user name:</td>
          <td><input type="text" name="username" id="username"></td>
        </tr>
        <tr>
          <td>password:</td>
          <td><input type="password" name="password"></td>
        </tr>
        <tr>
          <td colspan="2" class="centered"><input type="submit" value="Log In"></td>
        </tr>
      </table>
      <br>
    </form>
</div>
</body>
</html>

The PHP login action page is actionLogin.php:

<?php
  session_start();
  require_once "config.php";
  if (empty($_POST['username']) || empty($_POST['password'])) {
    $_SESSION['error_message'] = "Some of your login information is missing.  Please try again.";
    $filename = "loginForm.php";
    if (strpos($_SERVER['SERVER_NAME'],'localhost') === false)
    {
      header("Location: " . constant("SECUREURL") . "/PHPStuff/" . $filename);
      exit();
    } else {
      header("Location: " . constant("LOCALURL") . "/PHPStuff/" . $filename);
      exit();
    }
  } else {
  
    $dbobject = new mysqli(DBSERVER, DBUSER, DBPWD, DBNAME);
    /* check connection */
    $db_error = $dbobject->connect_errno;
    if ($db_error)
    {
        printf("<p>Connect failed: %s</p>\n", $db_error);
        exit();
    }
  
	
    $rawPassword = $_POST['password'];
    $querystr  = sprintf("
SELECT *
FROM login
WHERE UserName = '%s'", $_POST['username']);
    $resultset = $dbobject->query($querystr);
    if ($resultset === false) {
      $_SESSION['error_message'] = 'Database problem.';
      $filename = "loginForm.php";
      if (strpos($_SERVER['SERVER_NAME'],'localhost') === false)
      {
        header("Location: " . constant("SECUREURL") . "/PHPStuff/" . $filename);
        exit();
      } else {
        header("Location: " . constant("LOCALURL") . "/PHPStuff/" . $filename);
        exit();
      }
    }
    else {
      $row = $resultset->fetch_assoc();
      if (!empty($row) && password_verify($rawPassword, $row['Pwd']))
	  {
        $_SESSION['successlogin'] = true;
         $filename = "checkbook.php";
      } 
	  else 
	  {
        $_SESSION['error_message'] = 'Your login information is incorrect.  Please try again.';
        $filename = "loginForm.php";
      }
      if (strpos($_SERVER['SERVER_NAME'],'localhost') === false)
      {
        header("Location: " . constant("SECUREURL") . "/PHPStuff/" . $filename);
        exit();
      } else {
        header("Location: " . constant("LOCALURL") . "/PHPStuff/" . $filename);
        exit();
      }
    }
  }
?>

The logout page is loginAndLogout.php:

<?php
  session_start();
  require_once "config.php";
  if (!empty($_POST['autoLogoff']) && $_POST['autoLogoff'] == "1")
  {
    unset($_SESSION['successlogin']);
    $filename = "loginForm.php";
    if (strpos($_SERVER['SERVER_NAME'],'localhost') === false)
    {
      header("Location: " . constant("SECUREURL") . "/PHPStuff/" . $filename);
      exit();
    }
    else
    {
      header("Location: " . constant("LOCALURL") . "/PHPStuff/" . $filename);
      exit();
    }
  }

  if (empty($_SESSION['successlogin']))
  {
    $filename = "loginForm.php";
    if (strpos($_SERVER['SERVER_NAME'],'localhost') === false)
    {
      header("Location: " . constant("SECUREURL") . "/PHPStuff/" . $filename);
      exit();
    }
    else
    {
      header("Location: " . constant("LOCALURL") . "/PHPStuff/" . $filename);
      exit();
    }
  }
?>

Escaping Strings

We will talk in more detail about preventing outside attacks on your database, in an upcoming class session.

In the meantime, you should note the lines of code that look something like this in the action pages that we have looked at in this e-handout:

$dbobject->real_escape_string($descr)

This method real_escape_string() replaces certain characters that could be typed into the input form for this page, which could potentially cause errors in the database execution, or could be used by bad people to attack your database.

In particular, if the person typing information into your input form uses an apostrophe (') anywhere in the text that they are typing, the MySQL engine will most likely stop processing because of an internal error. This real_escape_string() method is a handy way to allow the user to include those apostrophes.