Murach's PHP and MySQL, C4 © 2014, Mike Murach & Associates, Inc. Slide 1 Chapter 19 Using procedural mysqli with a MySQL database
Murach's PHP and MySQL, C4
© 2014, Mike Murach & Associates, Inc.
Slid
e 1
Chapter 19
Using procedural mysqli with a MySQL database
Murach's PHP and MySQL, C4
© 2014, Mike Murach & Associates, Inc.
Slid
e 2
Applied
1. Given the specifications for a database application that requires
only the skills that are presented in this chapter, develop the
application. That includes:
Connecting to a MySQL database
Executing SELECT, INSERT, UPDATE, and DELETE
statements
Using procedural mysqli functions
Getting the data from the result sets that are returned by SQL
statements
Objectives
Murach's PHP and MySQL, C19
© 2014, Mike Murach & Associates, Inc.
Slid
e 3
Pros
Is included with PHP 5.1 and later and available for 5.0.
Provides an object-oriented interface.
Provides a consistent interface that’s portable between other
database servers such as Oracle, DB2, and Microsoft SQL Server,
and PostgreSQL.
Takes advantage of most new features found in MySQL 4.1.3 and
later.
Cons
Doesn’t work with versions of PHP 4.x, 3.x, or earlier.
Doesn’t take advantage of some advanced features found in
MySQL 4.1.3 and later, such as multiple statements.
PDO (PHP Data Objects)
Murach's PHP and MySQL, C19
© 2014, Mike Murach & Associates, Inc.
Slid
e 4
Pros
Is included with PHP 5 and later.
Provides both an object-oriented interface and a procedural
interface.
Takes advantage of all new features found in MySQL 4.1.3 and
later.
Cons
Can’t be used with other database servers.
mysqli (MySQL improved extension)
CONNECTING TO A
DATABASE
PHP offers three different ways to connect to and interact with a MySQL database:
1. Original MySQL extension – no longer developed, not recommended
2. MySQL Improved: MySQLi – designed specifically for MySQL so is not easily portable to other databases
Procedural
Object-oriented
3. PHP Data Objects: PDO – software neutral, preferable of database flexibility is important.
We will start with MySQLi procedural…
COMMUNICATING TO
MYSQL
All PHP methods follow the same sequence:
1. Connect to the MySQL database using the hostname,
username, password, and database name.
2. Prepare an SQL query.
3. Execute the query and save the result.
4. Extract the data from the result (usually with a loop.)
5. Close the connection to the database.
EXAMPLE
<?php # - mysqli_connect.php
// This file contains the database access information.
// It establishes a connection to MySQL and selects the database
// Set the database access information as constants:
DEFINE ('DB_USER', 'your user name');
DEFINE ('DB_PASSWORD', 'your sql password');
DEFINE ('DB_HOST', '127.0.0.1');
DEFINE ('DB_NAME', 'your user name');
// Make the connection:
$dbc = mysqli_connect (DB_HOST, DB_USER, DB_PASSWORD, DB_NAME) OR die ('Could not connect to MySQL: ' . mysqli_connect_error() );
echo 'Connection successful!';
CALLING THE
CONNECTION FILE
Use the require() function, which will halt the script
if it is unsuccessful, to connect to the database:
<?php
require ('../mysqli_connect.php');
?>
EXECUTING SIMPLE
QUERIES
$r = mysqli_query($dbc, $query);
• For simple queries like, INSERT, UPDATE, DELETE, etc.
(which don't return records), the function will return either
TRUE or FALSE.
• For complex queries like SELECT, which return results of
the query as a table, $r will be a pointer to the result or
FALSE if it did not work.
EXECUTING SIMPLE
QUERIES
Write the query and assign it to a variable:
$q = "DELETE from SF_products where id = 3";
Execute the query:
$r = mysqli_query($dbc, $q);
EXECUTING SIMPLE
QUERIES WITH VARIABLES
$category_id = 1;
$code = 'strat';
$name = 'Fender Stratocaster';
$price = 699.99;
Write the query and assign it to a variable:
$query = "INSERT INTO products
(categoryID, productCode, productName, listPrice)
VALUES
($category_id, '$code', '$name', $price)";
Execute the query:
$r = mysqli_query($dbc, $query);
CLOSE THE EXISTING
CONNECTION
mysqli_close($dbc);
• optional because PHP will close the connection at the end
of the script
• makes for good programming form anyway
EXECUTING 'SELECT'
QUERIES
A MySQL SELECT query typically generates one or more
rows of information that has to be handled by the script.
The same command is used to execute the query:
$r = mysqli_query($dbc, $q);
$r is the query result variable. In the case of a SELECT
query, $r is a pointer to the results table.
The mysqli_fetch_array() function returns one row of the
result at a time, in array format:
while ($row = mysqli_fetch_array($r) )
{ //Do something with $row
}
EXECUTING 'SELECT'
QUERIES
Notes:
The query must be executed first and then the results are processed.
Remember that SQL variables are case-sensitive – you must reference
them exactly as they are in the database.
Instead of mysqli_fetch_array($r, MYSQLI_ASSOC) , you could use
mysqli_fetch_assoc($r)
mysqli_free_result ($r); is an optional (but good practice) command to
free the memory taken by $r.
COUNTING
RETURNED RECORDS
$num = mysqli_num_rows ($r);
• Takes the results variable as the argument
• Used to:
• Determine how many rows are in a given result. For example, to check if a userid already exists in a database.
• Paginate query results (Ch. 10)
$num = mysqli_affected_rows ($dbc);
• Takes the database connection as the argument
• Can be used to determine the success of UPDATE, DELETE, or INSERT queries.
SQL SECURITY
1. Protect the MySQL access information
• Keep it outside of the Web directory so that it is never
viewable though a Web browser.
2. Don't reveal too much about the database
• Don't allow users to the PHP error messages or SQL error
messages.
• They are useful to display during development for
debugging, but remove them when the site goes live.
3. Be especially careful with user-submitted data
• Never trust it!
SQL SECURITY
SQL statements that don't include parameters are safe from XSS or
SQL injection attacks. For example:
$q=SELECT * FROM products; is safe
$q=SELECT * FROM products
WHERE productID = $product_id; is not safe
$q = "INSERT INTO products
(categoryID, productCode, productName, listPrice)
VALUES
($category_id, '$code', '$name', $price)"; is not safe
PREPARED
STATEMENTS
• Prepared statements take the form of a template into
which certain constant values are substituted during each
execution.
• Prepared statements are resilient against SQL injection,
because parameter values, which are transmitted later
using a different protocol, need not be correctly escaped.
If the original statement template is not derived from
external input, SQL injection cannot occur.
• The overhead of compiling and optimizing the statement is
incurred only once, although the statement may be
executed multiple times.
10/2/2015
18
PREPARED STATEMENTS
WORKFLOW
10/2/2015
19
1. Prepare: The statement template is created leaving
parameters unspecified by using placeholders
(labelled "?" below):
INSERT INTO product (name, price) VALUES (?,?)
2. The DBMS parses, compiles, and performs query
optimization on the statement template, and stores the result
without executing it.
3. Execute: At a later time, the application supplies (or binds)
values for the parameters, and the DBMS executes the
statement (possibly returning a result). The application may
execute the statement as many times as it wants with different
values.
Murach's PHP and MySQL, C19
© 2014, Mike Murach & Associates, Inc.
Slid
e 20
prepare($sql_statement)
Four methods of the mysqli_stmt class bind_param($fs, $v1[, $v2]...)
bind_result($v1[, $v2]...)
execute()
fetch()
close()
A method of the mysqli class
PREPARED
STATEMENTS
Can be used for INSERT, UPDATE, DELETE, and
SELECT queries.
1. Define the query string replacing values with
question marks.
$q = "SELECT * FROM users WHERE id = $id";
becomes
$q = "SELECT * FROM users WHERE id = ?";
PREPARED
STATEMENTS
2. Prepare the statement with mysqli_prepare();
$stmt = mysqli_prepare($dbc, $q);
MySQL will parse the query, checking for correct SQL
syntax, as well as valid table and column names, but it
won't execute it.
PREPARED
STATEMENTS
3. Bind the PHP variables to the query's placeholders:
mysqli_stmt_bind_param(prepared_stmt,
bound_value_type, value);
mysqli_stmt_bind_param($stmt, 'i', $id);
Bound Value Types:Letter Represents
d Decimal
i Integer
b Blob (binary data)
s All other types
PREPARED
STATEMENTS
4. Lastly, execute the statement:
mysqli_stmt_execute($stmt);
ANOTHER EXAMPLE
// Make the query:
$q = 'INSERT INTO FM_messages (forum_id, parent_id,
user_id, subject, body, date_entered) VALUES (?, ?, ?, ?, ?,
NOW())';
// Prepare the statement:
$stmt = mysqli_prepare($dbc, $q);
// Bind the variables:
mysqli_stmt_bind_param($stmt, 'iiiss', $forum_id, $parent_id,
$user_id, $subject, $body);
WHY IS THIS MORE
SECURE?
While in case of prepared statements we don't alter our program, it
remains intact.
We are sending a generic program to the server first:
$query = "SELECT * FROM users WHERE id=?";
$stmt= mysqli_prepare($dbc, $query);
where the data is substituted by some variable called "placeholder".
Note that the very same query is being sent to the server, without any
data in it.
Then the data is bound and sent with the second request, totally
separated from the query itself:
mysqli_stmt_bind_param($stmt, 'i', $id);
mysqli_stmt_execute($stmt);
so, it can't alter our program and do any harm.
WHY IS THIS MORE
SECURE?
The query and the data are sent to the SQL server separately.
The root of the SQL injection problem is mixing of the code and the data.
$expected_data = 1;
$query = "SELECT * FROM users where id=$expected_data"; will produce a regular query, while this code:
$spoiled_data = "1; DROP TABLE users;"
$query = "SELECT * FROM users where id=$spoiled_data";
will produce the malicious sequence:
SELECT * FROM users where id=1; DROP TABLE users;
It works because we are adding data directly to the program body and it becomes a part of the program.