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:
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:
you’ll need to use two commands:
Here’s how mysql and mysqli functions match up.
Close MySQL connection |
|
|
Open a connection to a MySQL server |
You must use |
You don’t need |
Return the text of the error message from previous MySQL operation |
|
|
Escape a string |
The order of arguments is opposite, expects the string, then the connection (link). |
Expects the connection (link) followed by the string. |
Fetch a result row as an associative array, a numeric array, or both |
|
|
Get number of rows in result |
|
|
Execute a MySQL query |
|
|
Escape special characters in a string |
The order of arguments is opposite, expects the string, then the connection (link). |
Expects the connection (link) followed by the string. |
Select a MySQL database |
The order of arguments is opposite, expects the string, then the connection (link). |
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:
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:
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
.
You can set very specific user privileges, even control what your user can do to a specific column. To learn more, check out Head First SQL.
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:
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:
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:
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.
When the code runs, you’ll see this:
Error: Balance less than $1000.
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.
Objects can be easily reused. They are designed to be independent of the code where they are used and can be reused as needed.
The code is easier to understand and maintain. If a data type needs to change, the change occurs only in the object, nowhere else in the code.
A big disadvantage is that, in general, OO code can be longer and take more time to write. If you simply need to display the lyrics from one song, then writing a small procedural program might be your best bet. But if you think you might want to build that online karaoke app, consider diving further into object-oriented PHP.
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.
Remove phpinfo()
references. When you first start building PHP applications on new web servers, you’ll probably create a script that contains the phpinfo()
function, so you can see what version of PHP you are using and if it has MySQL support, along with a list of other installed libraries. It’s fine to check with phpinfo()
, but you should remove that function after you’ve taken a look. If you don’t, any hacker out there who discovers a new PHP vulnerability will be able to see if your site is susceptible to it.
If you aren’t using a web hosting service and have access to the php.ini
file, there are a few changes you can make to it to further secure your PHP applications. Ironically, the location of your php.ini
file can be found by using phpinfo()
:
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.
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.
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:
Any data that you receive, such as form input, needs to be validated so that hacker code is detected before it can harm your application. If you assume the data is bad until you prove that it’s not through validation, you’ll be much safer.
Use built-in PHP functions such as strip_tags()
to help you sanitize external data. strip_tags()
is a great function that removes any html tags from a string. So if you use strip_tags()
on Ethel’s $_POST['name']
, you’ll end up with this:
window.location='http://ethelrulz.com'
While this is still not a name, it won’t actually redirect the browser because the important JavaScript tags have been removed.
Start with the most restrictive validation you can, and then only ease up if you have to. For example, if you begin by accepting only numbers in a phone number field, then start allowing dashes or parentheses, you’ll be much safer than if you allowed any alphanumeric characters in the first place. Or in the case of Guitar Wars, if we don’t allow anything except letters in the name field, we’ll never even get the less than sign (<
) that opens Ethel’s evil JavaScript code. Regular expressions (Chapter 11) can go a long way toward making sure only the exact data you want is allowed.
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:
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 |
| logical |
| logical |
| 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.
Suppose your application needed to output text in Greek.
Consider the kinds of things you sometimes have to do with strings, such as needing to know the length of them or sorting them. It’s straightforward in English, but when you are working with characters in other languages, string operations become more complicated.
Unicode is a set of characters and technologies to encode them. In Unicode, the Greek character that looks like a triangle has a specific numeric value assigned to it, along with other characters in other languages. Unicode is a standard, which means it receives wide support from major technology providers. In Unicode, every character has a unique number, no matter what language, program, or platform is used. Before the advent of PHP 5, PHP had no real support for Unicode. PHP 6 has enhanced support for Unicode strings in its functions and functions built specifically for creating and decoding Unicode.
PHP 5 offers an object-oriented programming model but still allows for the mingling of procedural style. PHP 6 moves farther into the object-oriented realm. One of the biggest changes here is that dynamic functions will no longer be permitted to be called with static syntax. There are any number of small, but important, changes to the way PHP handles its OO code that make it more consistent with other OO languages such as C++ and Java.
None of the code in this book uses dynamic functions, so you don’t have to worry about any of the code not working in PHP 6.
A few other changes are:
Both XML Reader and XML Writer will be extensions in PHP 6, making it easier to work with XML files.
The register_globals
, magic_quotes
, and safe_mode
options in the php.ini
file will no longer be available.
The ereg extension, which provided another way to build regular expressions, is removed. Fortunately, the same preg_match()
code covered in this book will be the main way to build regular expressions in PHP 6.
A 64-bit integer type will be added.
Multi-dimensional arrays will be able to use foreach
.
Version 6 of PHP is, more than anything, a version that cleans up and refines the language.
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!
One of the most impressive PHP projects to date, Drupal is a powerful content management system that can be used to build just about any kind of content-driven web site. NASA, The Onion, the Electronic Frontier Foundation, and Popular Science all use Drupal for their web sites. It’s flexible enough to build just about anything that is heavy on content. Check it out at http://drupal.org/
.
Another really nice PHP-based content management system is Joomla!, which you can learn about at http://www.joomla.org/.
A category killer in the realm of online message boards (forums), phpBB is easy-does-it when it comes to building your own forum. It is extremely flexible and hard to beat at the one thing it does so well—managing threaded discussions. Find out more at http://www.phpbb.com/
.
If image hosting is what you have in mind, Coppermine Gallery is the PHP application to check out. In an era of Flickr, Photobucket, Shutterfly, and Snapfish, hosting your own photo library sounds downright quaint. But with control comes power, and if you want complete control over your photos, take a look at Coppermine Gallery at http://coppermine-gallery.net/
.
One of the heavy hitters in the blogosphere, WordPress is PHP-based blogging software that lets you build and maintain a blog with minimal hassle. There’s lots of competition out there, so you might want to do some exploring, but you could do worse than to pick WordPress if you’re launching a blog. Download it at http://wordpress.org/
.
Because reusing code isn’t always as simple as it sounds—sometimes it requires PHP skills.
Many PHP software packages still require customization, and that often requires some strong PHP development skills. Not only that, but you may elect to only reuse a small component of someone else’s code, or not reuse it at all. Either way, by having PHP knowledge, you have options, and options are always a good thing!