Appendix A. Leftovers: The Top Ten Topics (we didn’t cover)

image with no caption

Even after all that, there’s a bit more. There are just a few more things we think you need to know. We wouldn’t feel right about ignoring them, even though they only need a brief mention. So before you put the book down, take a read through these short but important PHP and MySQL tidbits. Besides, once you’re done here, all that’s left are a couple short appendices... and the index... and maybe some ads... and then you’re really done. We promise!

With the exception of XML functions in Chapter 13, most of the code in this book will run on PHP 4 servers with only a little modification. We’ve used the mysqli family of functions in this book, which are only available in PHP 4.1 and later, and since the library has to be manually installed, some servers won’t support mysqli.

Mysqli functions are generally faster, but this really only begins to matter when your database becomes huge. Small or average databases won’t be perceptibly slower with the older mysql functions. This section is designed to tell you how to retrofit your mysqli functions to work as mysql functions with older versions of PHP.

If you see:

$dbc = mysqli_connect(localhost, 'mork', 'fromork');
mysqli_select_db($dbc, 'alien_database');

you’ll use:

image with no caption

In general, you just remove the i from mysqli, making it mysql, and then swap the order of the arguments so that the database connection variable ($dbc in this example) appears last.

But it gets a little trickier when the mysqli_connect() function sidesteps mysqli_select_db() and uses a database name. There’s nothing quite like that in the mysql family of functions. For the single mysqli_connect() function that uses a database name, you’ll need two mysql functions.

If you see:

image with no caption

you’ll need to use two commands:

image with no caption

Here’s how mysql and mysqli functions match up.

Close MySQL connection

mysqli_close(conn)

mysqli_close(conn)

Open a connection to a MySQL server

mysql_connect(host, username, password)

You must use mysql_select_db() to select a database.

mysqli_connect(host, username, password, database)

You don’t need mysqli_select_db() to select a database.

Return the text of the error message from previous MySQL operation

mysql_error(conn)

mysqli_error(conn)

Escape a string

mysql_escape_string(string, conn)

The order of arguments is opposite, expects the string, then the connection (link).

mysqli_escape_string(conn, string)

Expects the connection (link) followed by the string.

Fetch a result row as an associative array, a numeric array, or both

mysql_fetch_row(result)

mysqli_fetch_row(result)

Get number of rows in result

mysql_num_rows(result)

mysqli_num_rows(result)

Execute a MySQL query

mysql_query(query, conn)

mysqli_query(conn, query)

Escape special characters in a string

mysql_real_escape_string(string, conn)

The order of arguments is opposite, expects the string, then the connection (link).

mysqli_real_escape_string(conn, string)

Expects the connection (link) followed by the string.

Select a MySQL database

mysql_select_db(dbname, conn)

The order of arguments is opposite, expects the string, then the connection (link).

mysqli_select_db(conn, dbname)

Expects the connection (link) followed by the string.

Suppose you’ve created a web application that only allows visitors to SELECT data from your table. You perform queries on your data using a specific database, and MySQL gives you power over your data.

But consider this: the login and password you use in your mysqli connection string would, if connected directly to the database via the MySQL terminal or GUI, allow the user to INSERT, UPDATE, and DELETE data.

If your application doesn’t need to do those things, there’s no reason why the user/password you are using to connect with needs to be able to. With MySQL, you can limit the access to your database. You can tell MySQL to only allow the user to SELECT. Or SELECT and INSERT. Or any combination you need.

And what’s even more impressive, you can control access to specific tables. For example, if your application only works with a table called alien_info and doesn’t need access to the cyborg_info table, you can limit it.

First, you may want to create an entirely new user/password to be used for your application. You can do this in the MySQL terminal:

image with no caption

Then you can use the MySQL GRANT command to control what alienguy can do to your database. If he only needed to SELECT and INSERT data into your database, this would work:

image with no caption

If you don’t like using the MySQL terminal to create users and set privileges, you can download and install a handy program caled MySQLAdministrator. Get it here: http://dev.mysql.com/downloads/gui-tools/5.0.html.

The MySQL Administrator lets you control your user accounts and what each user account can access in your database. It even allows you to specify which kind of queries that user can perform on each table in your database. To control the access every user has to each table and each query, open the MySQL Administrator application, and click on the Accounts tab.

Here’s the interface and an overview of how to control what each user can do. First, create an account:

image with no caption

In many of our code examples, you’ll see lines like this:

mysqli_connect(localhost, 'mork', 'fromork') or die ('Could not connect.')

When this command fails, the words “Could not connect.” are displayed on the web page. It tells us that something went wrong, but it doesn’t give us information beyond that.

Fortunately, PHP offers a function, mysql_error(), that will give us a clue as to exactly what went wrong. Consider this code where we are trying to connect to a MySQL server that doesn’t exist:

image with no caption

This will return clear information as to what actually went wrong when the mysqli_connect() function fails. You can also use mysqli_error() with other mysqli functions:

image with no caption

Here are some other error messages you might see:

Table 'test.no_such_table' doesn't exist
Can't create table
Can't create database 'yourdatabase'; database exists
Can't drop database 'yourdatabase(; database doesn't exist

There are dozens more, and it would be a waste of paper to list them here. Browse on over to this site to get more information:

http://dev.mysql.com/doc/refman/5.0/en/error-messages-server.html

If you’re retrofitting your mysql functions, as mentioned in #1, you can use mysql_error() instead of mysqli_error().

Exception handling allows you to change the normal flow of your code and execute a special block of code when a specific exception occurs. PHP 5 and 6 offer exception handling. Here’s a brief introduction.

Let’s say you want to withdraw $200 bucks from an ATM.

But maybe you’re required to have a minimum balance of $1000, and this withdrawal will put you under $1000. That isn’t allowed.

Transaction failed!

Here’s how this scenario might play out in PHP code with the help of exception handling to catch the failure.

image with no caption

When the code runs, you’ll see this:

Error: Balance less than $1000.

Exception handling consists of three blocks of code:

image with no caption

Object-oriented languages use a very different progamming model than their procedural counterparts. You’ve been using PHP procedurally, but it also has an object-oriented side. Instead of a chronological step-by-step set of instructions, particular structures become objects. Objects include not only a definition of your data, but also all the operations that can be performed on it. When you use object-oriented PHP, you create and work with objects.

Before we discuss why you might want to use OO PHP, let’s write some:

Instead of a chronological step-by-step set of instructions, your data structures become objects. Objects include not only a definition of your data, but also all the operations that can be performed on it. In our Song example, we set the title and lyrics of the song inside the class, and we create the sing() method inside the class. If we needed to add more functionality to our Song object, we’d add new methods and variables to our Song class. For example, if we wanted the songwriter for each song to be associated with each song object, we could add that as a variable in our class.

The power of OO really shines as an application grows. Suppose we decided to use the Song class as part of a karaoke application with hundreds or even thousands of individual song objects, all with their own unique titles, lyrics, and songwriters. Now let’s say someone wants to choose from only songs that were written by Elvis. All we’d have to do is look at the songwriter instance variable of each object.

And to actually feed the lyrics to the karaoke application? We could just call the sing() method on each song object when it is being performed. Even though we’re calling the exact same method on each object, it is accessing data unique to each of the objects.

There are some simple steps you can follow to protect your PHP scripts from those nefarious hackers that are crouched over their keyboards waiting for you to slip up.

Here are some specific settings you should consider changing in the php.ini file. Open the file in a text editor, make the changes, save them, and then restart your web server.

safe_mode = On

When you turn on safe_mode, no PHP scripts can be called by another script with a different owner on the same web server. Obviously, if you need to allow scripts from other owners to call yours, you can’t use this setting.

open_basedir = directory[:...]

This restricts the scripts and files that PHP will be able to execute or access to this directory and subdirectories beneath it.

expose_php = Off

With this set to On, every web browser that visits your site will be sent header information that reveals information about you PHP server. Turning it off hides that information and makes your server a little less exposed.

display_errors = Off

Once you’ve developed your application and are running it on your live web server, you don’t need to see all those error messages. Hopefully, you’ve already addressed errors, but sometimes things slip through the cracks. To hide the error messages from site visitors, set this to Off.

log_errors = On

This sends your errors to an error log. When you want to check your application for errors, this is a good place to begin. With display_errors set to Off and log_errors set to On, you’ll be able to see problems, but your site’s visitors won’t.

error_log = filename

You’ll have to check with your particular web server software to locate this file. This is where your errors will be written when log_errors is set to On.

You may have heard of cross-site scripting sometimes referred to as XSS. Cross-site scripting is an attack against a web app where script code is passed to your form processing script and hijacks your output. It’s a big security problem in PHP web apps. Let’s take a look at precisely what it is and how to defend against it.

Cross-site scripting usually takes advantage of sites that display user-submitted data. Any data you get from your users and display could potentially be corrupt and cause visitors to your site to be vulnerable to a hacker.

image with no caption

Using an XSS attack, a hacker can do any number of things. One of the worse is to redirect your results page to a page on a site under their control that might ask the user for further information. Your user might not notice that he’s no longer on your site, and since he trusts your site, he might willingly submit sensitive information directly on the attackers server.

Here’s how it might happen on the Guitar Wars site:

Ethel, instead of submitting her name in the Name field on the form, types in some JavaScript code. In the example, she’s using the window.location function to redirect the browser to her own site. And since she controls her own site, she can show the visitor anything she wants, including a site that looks just like Guitar Wars. She could do something even more nefarious with sites that expect people to submit more important information than high scores, such as financial information.

image with no caption

There are other, even more insidious things that she could do, including stealing cookies or presenting the user with a screen that appeared to be a login screen. As soon as the user logs in, she has his username and password and can pretend to be him back on the original site.

So how do you avoid cross-site scripting attacks on your web applications?

Fortunately, if you are validating your data, you are already on the road to protecting your application. You’ve already learned how to do just that in Guitar Wars. Here are three guidelines that will keep your applications safe:

Consider this line of code.

image with no caption

The value stored by $marbles could be either 1 or 4. We can’t tell from the code, but we can assume certain rules of precedence. By precedence, we mean the order in which they are executed. Operators in PHP are carried out in a certain order. In the example above, the division will take place before the subtraction does, so $marbles will equal 1.

Depending on what we need our code to output, we could have written it two different ways

$marbles = (4 / 2) - 1;
$marbles = 4 / (2 - 1);

In the first expression, we divide 4 by 2 and then subtract 1. In the second case, we subtract 1 from 2 and then divide 4 by the resulting 1. Using parentheses allow you to precisely control the order of operations. But knowing the precedence of operators in PHP can help you figure out what’s going on in a complex expression. And, trust us, it will help you debug your code when you’ve forgotten to use parentheses.

Before we get to the PHP operator precedence list, here’s another reason why you should use parentheses. Consider this:

image with no caption

No precedence rules apply here. The result could be either 3 or -1. This is pretty confusing when you’re writing code. Instead, it’s better to code with parentheses, like in these two lines:

$marbles = 4 - (3 - 2);
$marbles = (4 - 3) - 2;

Now the list, from highest precedence (evaluated first) to lowest (evaluated last).

Operator

Operator Type

++ --

increment/decrement

*/ %

arithmetic

+ - .

arithmetic and string

< <= > >= <>

comparison

== != === !==

comparison

&&

logical

||

logical

= += -= *= /= .= %= &= |= ^= <<= >>=

assignment

and

logical

xor

logical

or

logical

As of the writing of this book, PHP 5 is the latest production version of PHP. But PHP 6 is being worked on and is available for developers here: http://snaps.php.net/.

The differences between PHP 4 and 5 are much greater than between 5 and 6. In many ways, 6 offers a refinement of the object-oriented features introduced in 5. Other changes include more support for XML and Unicode.

It’s not always necessary to write your own PHP code from scratch. Sometimes it’s best to reuse someone else’s. The following are several popular and highly successful PHP-based software packages that you should consider using if you have a need and would prefer not reinventing the PHP wheel. Oh, and they’re all free!