Accessing MySQL from PHP

This page is written to give you a very brief overview of accessing a MySQL database using PHP’s MySQLi class. We will cover the basics of querying tables, retrieving results, updating tables, and error handling.

Establishing a Connection

MySQL is a separate server process from your PHP code. The first step to accessing the database system from your program is establishing a connection. Connecting is as simple as just instantiating a new instance of MySQLi. For example, if you want to connect to MySQL running locally (i.e., on localhost) as the user cs143 with the empty password to use the datababse class_db, you need to execute the following statements:

$db = new mysqli('localhost', 'cs143', '', 'class_db');
if ($db->connect_errno > 0) { 
    die('Unable to connect to database [' . $db->connect_error . ']'); 
}

The database name is optional and can be omitted. If you omit the database name you must be sure to prefix your tables with the database in all of your queries.

Issuing Queries

To issue a query (select, update, insert, delete), you can use the query() function. To read all of the data from a table named “Movie” in the class_db database using the previously-established connection, we’d run the following code:

$query = "SELECT * FROM Movie";
$rs = $db->query($query);

Retrieving Results

The above query returns a mysqli_result object, which contains the results of the query. We can retrieve the actual values row by row using the function fetch_assoc(). This function returns the column values of the retrieved row in an associative array, or FALSE if there are no more results. Typically we want to retrieve all results of the query, which can be done with a simple loop:

while ($row = $rs->fetch_assoc()) { 
    $id = $row['id']; 
    $title = $row['title']; 
    print "$id, $title<br>"; 
}

In case you need to check if a returned column value is NULL, you can use the PHP function is_null() like is_null($row['title']).

Number of Returned Rows

Each mysqli_result object that is returned has a variable defined which is called num_rows, so all we need to do is access that variable by doing:

print 'Total results: ' . $rs->num_rows;

Free Result

It’s advisable to free a result when you’ve finished playing with the result set, so in the above example we should put the following code after our while() loop:

$rs->free();

This will free up some system resources, and is a good practice to get in the habit of doing.

Updating Values

The above example shows a simple select query. Issuing other query types (insert, update, delete) is similar. If we wish to update all move titles to add "Movie: " at the beginning, we’d issue the following query:

$query = "UPDATE Movie SET title = CONCAT('Movie: ', title)";
$db->query($query);
$db->commit();

Note that after you issue data modification statements, you have to call commit() in order to ensure that the changes are permanently “committed” in the database.

Number of Affected Rows

When running an UPDATE query you sometimes want to know how many rows have been updated, or deleted if running a DELETE query, this is a variable which is inside the mysqli object.

print 'Total rows updated: ' . $db->affected_rows;

Close connection

Don’t forget, when you’ve finished playing with your database to make sure that you close the connection:

$db->close();

Basic Error Handling

Many MySQLi functions return resources or boolean types to indicate success and failure. You can use these return values to take proper action when a command fails. Sometimes it may be helpful to get more detailed information on why a function failed. To fetch the MySQL error, you can reference error variable of the MySQLi object like the following:

$query = "SELECT * FROM Movie"; 
$rs = $db->query($query);
if (!$rs) {
    $errmsg = $db->error; 
    print "Query failed: $errmsg <br>"; 
    exit(1); 
}

Handling User Input

As a last step, we want to make one very important note: your code should never trust user input. That is, if you take input from a user (such as in an HTML form) which will be part of your query, you must always “sanitize” their inputs. For example, the user’s input may contain escape characters which must be properly handled to avoid errors, or worse, data corruption.

Escaping User Inputs

One way to sanitize user inputs is to use the function real_escape_string(). This function takes an input string, and produces a string which has all “special characters”, such as ', properly escaped.

Prepared Statements

Prepared statements are a bit complex than using real_escape_string() function, but are much safer and can help avoid a lot of the potential security issues related to user inputs.

Define a statement

Let’s try to grab all movies’ id and title from the Movie table that was released in year 1990. We’d firstly define the SQL statement that we’d use:

$statement = $db->prepare("SELECT id, title FROM Movie WHERE year=?");

Prepared statements basically work by placing (a few) ? in the statement, which will be eventually substituted by a string, integer, blob or double value. The question mark in the above statement is where we’re going to be assigning the integer 1990.

Bind parameters

We simply use the method bind_param to bind a parameter to a question mark in the statement. You must specify the type as the first parameter then the variable as the second — so for instance we’d use i as the first parameter (for string), and our $year variable as the second:

$year = 1990; 
$statement->bind_param('i', $year);

If we had 3 parameters to bind which are of varying types we could use bind_param('sdi', $title, $rating, $year) for example, where s, d, and i, represent string, double, and integer, respectively. Note the types are not separated at all as the first parameter.

Execute the statement

No fuss, no mess, just execute the statement so that we can play with the result:

$statement->execute();

Iterating over results

Firstly we’ll bind the result to variables, we do this using the bind_result() method which allow us specify some variables to assign the result to. So if we assign the returned id and title to the variable $returned_id and $returned_title we’d use:

$statement->bind_result($returned_id, $returned_title);

Now we have to actually fetch the results, this is just as simple as the earlier mysqli requests that we were doing — we’d use the method fetch(), which returns will assign the returned values into the binded variables — if we’d binded some.

while ($statement->fetch()) { 
    echo $returned_id . ' ' . $returned_title . '<br>';
}

Close statement

Once you are done, don’t forget to forgo a few seconds of your time to close both the prepared statement and the database connection — keep your code neat, clean and lean:

$statement->close();
$db->close();