The PHP Anthology Volume 1, Chapter 1 – PHP Basics

PHP is a programming language that’s designed specifically for building Websites, and is both blessed and cursed with being remarkably easy to learn and use. Getting started is extremely simple. Before long, the typical beginner can put together a simple Website and experiment with the wealth of open source projects available through resources like HotScripts.

Unfortunately, the ease with which PHP-based sites can be developed also means you can quickly get yourself into trouble. As traffic to your site increases, along with the demand for more features and greater complexity, it’s important to gain a more intimate understanding of PHP, and to research application designs and techniques that have proved successful on large Websites. Of course, you can’t leap into programming and expect to know it all straight away. Even if you could, where would be the fun in that?

This series begins to address the key issues facing PHP developers today. It comprises 5 articles:

From Volume I: Foundations:

Chapter 1: PHP Basics
This chapter provides a summary of all the essentials you need in order to get around quickly in PHP, from how to use the manual, to understanding PHP error messages, and how includes work. There are also some tips for writing portable code, and we’ll take a look at some of the main PHP configuration pitfalls.

Chapter 2: Object Oriented PHP
The second chapter includes a run-down of PHP’s class syntax, as well as a primer that explains how all the key elements of the Object Oriented Paradigm apply to PHP. It’s essential preparatory reading for later chapters in this anthology.

Chapter 3: PHP and MySQL
This chapter provides you with all the essentials of MySQL, PHP’s favorite database. We start with the basics, covering important topics such as how to avoid SQL injection attacks. We then delve more deeply into many lesser known topics, such as MySQL FULLTEXT search facilities, how to repair corrupt tables and back up your database, and how to avoid writing SQL with PEAR::DB_DataObject. This chapter also serves as a "case study" in designing a class to handle connecting to, and the querying of, your MySQL database.

From Volume 2: Applications

Chapter 1: Access Control
Beginning with basic HTTP authentication, then moving on to application level authentication, this chapter looks at ways to control access to your site. Later solutions look at implementing a user registration system and creating a fine-grained access control system with users, groups and permissions.

Chapter 5: Caching
This chapter takes the fundamental view that "HTML is fastest," and shows you how you can take advantage of caching on both the client and server sides to reduce bandwidth usage and dramatically improve performance.

The Book

The 5 chapters in this series are excerpts from my new book. The PHP Anthology, Volume I and Volume II contains not only the 5 chapters above, but 12 more chapters, which explore a selection of topics ranging from text manipulation, dates and times, and error handling, to XML, alternative content types, and stats and tracking.

If you’d prefer to read the Adobe Acrobat PDF version of this information, you can download these 5 chapters, plus sample reference material, FREE.

Your Feedback

If you have a question about any of the information covered in this series, your best chance of a quick response is to post your query in the SitePoint.com Forums. Suggestions for improvement as well as notices of any mistakes you may find (one or two may have slipped through the cracks) are especially welcome –- submit these to SitePoint Book Support.

Are you ready to launch forth into the wonderful world of PHP? Let’s go!

Chapter 1: PHP Basics

In this first chapter, I’ll assume you’ve had a basic grounding in PHP, such as that provided in the first few chapters of Kevin Yank’s Build Your Own Database-Driven Website Using PHP & MySQL (ISBN 0-9579218-1-0), and instead concentrate on the essentials of "getting around" in PHP.

In this chapter, you’ll find out where to get help – a defence against those that bark "Read the manual!" at you – and how to deal with errors in your code. We’ll also discuss some general tips for keeping your code portable, and provide other essential roughage for your PHP diet. Not everything here fits under the heading of "basic" – there may also be a few surprises in store for the more experienced PHP developers, so keep your eyes peeled!

Be warned, though, that the discussion of PHP syntax is not the most invigorating of subjects – although it is essential to prepare for later chapters. If you start to struggle, remember the line from The Karate Kid: you must learn "wax on, wax off" before you can perform the flying kick.

Where do I Get Help?

PHP is the most widely-used Web scripting language, running on over ten million domains around the world. For an open source technology that lacks any corporate funding whatsoever, its popularity may seem inexplicable. Yet PHP’s success is no mystery; it has one of the most active and helpful online communities of any technology. Recent estimates place the number of PHP developers worldwide at around 500,000 and given the nature of the medium, it’s fair to assume that a large proportion are active online. In other words, for developers of PHP-based Websites, help is only ever a few clicks away.

Reading the Manual

There’s a well known four letter abbreviation, RTFM (I don’t think it needs explaining here), which tends to be used to harass beginners in all areas of computing. While I can understand veterans might be unwilling to repeat endlessly the same, well documented instructions, I think the basic assumption should be that we all know how to read the manual in the first place.

The documentation for PHP is excellent, and is maintained by volunteers who make it their sole purpose to keep it up to date, understandable and relevant. The online version is extremely easy to navigate and contains further know-how in the form of annotations from developers across the globe. The manual is one of the areas in which PHP is truly exceptional; software houses like Sun and Microsoft still have a long way to go to provide this quality of material to developers working on their platforms.

The manual is also available in twenty-four different languages but as you’re reading this book I’ll assume you’re happy with the English version of the manual. It’s broken down into five main sections plus appendices. It’s worth knowing what kind of information can be found, and where – at least within the first four sections, which are the most relevant to the typical PHP developer.

Section I: Getting Started

http://www.php.net/getting-started

This section provides a short introduction to PHP with some basic examples. It then explains how to install PHP (describing all sorts of operating system-Web server combinations), and how to configure it in terms of modifying your php.ini file.

Not to be overlooked is the section on security, which covers the areas in which PHP developers often make mistakes that leave their applications open to abuse. Once again, the "price" of PHP’s ease of use is that it won’t always protect you from your worst mistakes, so it’s worth getting started on security as early as possible in your PHP career. You’ll find a summary of key security issues in Appendix C, Security Checklist, as well as in discussions throughout this book, where appropriate.

Section II: Language Reference

http://www.php.net/langref

This section covers the fundamentals of PHP as a programming language. Some of these are essential to your being able to achieve anything with PHP, while others become useful as you look for ways to improve your technique. Reading the whole lot in one sitting may well be like reading a dictionary. Fortunately, it’s possible to absorb much of the information contained in the language reference by reading the wealth of tutorials available online, and examining the code that’s used in open source PHP applications. Certainly, as you read this book, I hope you’ll pick up a thing or two about getting the most out of PHP. However, it is worth familiarizing yourself with the subjects contained in this section of the manual, and keeping them in the back of your mind for future reference.

Section III: Features

http://www.php.net/features

Covered here are the core elements of PHP that are generally focused on solving specific Web-related problems. Much of the Features section reads like an "executive summary" and, from a developers point of view, the information contained here may be better understood when you see it in action – for instance, in the examples we’ll see throughout this book.

Section IV: Function Reference

http://www.php.net/manual/en/funcref.php

This section makes up the real body of the manual, covering all aspects of the functionality available within PHP. This is where you’ll spend most of your time as you progress with PHP, so you’ll be glad to hear the PHP group has made a concerted effort to make this section easy to get around. It’s even fun, in an idle moment, just to trawl the manual and be amazed by all the things you can do with PHP. Yes, I did just describe reading a manual as "fun"!

The function reference is broken down into subsections that cover various categories of functions, each category corresponding to a PHP extension.

PHP Extensions

The notion of an extension can be a little confusing to start with, as many are distributed with the standard PHP installation. The String functions, which we’d be pretty hard-pressed to live without, are a case in point. In general, the PHP group distributes, as part of the default PHP installation, all the extensions they regard as being essential to developers.

Extensions regarded as "non-essential" functionality (i.e. they will be required by some, but not all developers) must be added separately. The important information appears under the heading "Installation" on the main page for each extension. Core extensions are described with the sentence "There is no installation needed to use these functions; they are part of the PHP core." Nonstandard extensions are examined in Appendix B, Hosting Provider Checklist.

Access to information within the Function Reference is available through the search field (top right) and searching within the "Function List". Note that searching within the function list examines only the Function Reference section of the manual. To search the entire manual you need to search within "Online Documentation."

Another handy way to get around is to "short cut" to functions by passing the name of the topic you’re interested in via the URL. For example, try entering the following in your browser’s address field: http://www.php.net/strings. This will take you to http://www.php.net/manual/en/ref.strings.php, which is the main page for the Strings extension. Looking at this page, you’ll see a list of all the functions made available by the extension; the same list is available in the menu on the left hand side.

Taking the strpos function as an example, enter the URL http://www.php.net/strpos (which takes you to http://www.php.net/manual/en/function.strpos.php). You will see the following information about the strpos function:

(PHP 3, PHP 4)

strpos -- Find position of first occurrence of a string

Description

int strpos (string haystack, string needle [, int offset])

Returns the numeric position of the first occurrence of needle in the haystack string. Unlike the strrpos(), this function can take a full string as the needle parameter and the entire string will be used.

If needle is not found, returns FALSE.

Line one contains the name of the function and line two lists the PHP versions in which the function is available. The third line tells you what the function actually does. In this case, it's a fairly terse explanation, but strpos really isn't a subject you can get excited about.

Under the Description heading is perhaps the most important line of all - the function's signature. This describes the arguments this function accepts and the value it returns in response. Reading from left to right, you have int, which tells you that the value returned by the function is an integer (in this case, the position of one piece of text within another). Next comes the name of the function itself, and then, in parentheses, the arguments this function takes, separated by commas.

Let's look at the argument string haystack. This says the first argument should be a string value, while haystack simply names the argument so that it can be referred to in the detailed description. Note that the third argument is placed inside square brackets, which means it's optional (i.e. you don't have to supply this argument).

Here's how you could use strpos:

Example 1.1. 1.php

<?php   
$haystack = 'Hello World!';  
$needle   = 'orld';  
 
// Use the strpos() function  
$position = strpos($haystack, $needle);  
 
echo 'The substring "' . $needle . '" in "' .  
    $haystack . '" begins at character ' . $position;  
?>

Notice that I've used strpos similarly to the way it appears in the manual. I used the variable names $haystack and $needle to make clear the way each relates to the explanation in the manual, but you can use whatever variable names you like.

The function signature convention is used consistently throughout the manual, so once you're used to it, you'll be able to grasp quickly how to use functions you haven't tried before.

Get Help When Problems Arise

If you make a mistake using an in-built function in PHP 4.3.0, the default error reporting mechanism of PHP will display an error message with a link that takes you directly to the manual.

If you're ever in doubt, be sure to read through the comments submitted by other PHP developers, which appear at the bottom of every page in the manual. Usually, you will at least see an example of how the function is used, which may solve the particular dilemma you've run into. In many cases you'll also find alternative explanations and uses for a function, which help broaden your understanding.

Further Help

Outside the manual, there are literally thousands of online resources from which you can get further help. I would dare to say that 99% of all the common problems you'll encounter with PHP have already been answered somewhere, and are available online. That means the most obvious (but sometimes forgotten) place to begin is Google, where a quick search for "PHP strpos problem" will give you an idea of what I mean.

There are also some excellent sites where you can get answers directly from other PHP developers (for free, of course - it's part of the PHP ethic). Perhaps the three biggest in the English language are:

Each of these uses vBulletin to host an online discussion and, as such, have very friendly and easy-to-use interfaces. All have very active memberships and you should find most questions answered within twenty-four hours.

Note that when you ask for help on forums, the principle of "helping others to help yourself" is important. Don't post a message that says, "This script has a problem" and paste in your entire PHP script. Narrow the problem down–identify the area where you're having problems and post this code snippet along with other relevant information, such as error messages, the purpose of the code, your operating system, and so on. People offering to help generally don't want to spend more than a few minutes on your problem (they're doing it for free, after all), so saving them time will improve your chance of getting a helpful answer.

Less convenient, but perhaps the most effective last resorts are the PHP mailing lists, where beginners are encouraged to use the PHP General list. The lists are available for limited browsing, though it's possible to search some of them using the search field from the PHP Website and selecting the list of your choice.

Zend, the company developing the core of the PHP engine, also hosts a fairly active forum for general PHP questions.

If you want to be guaranteed an answer, it's worth investigating PHP Helpdesk, a service run by Tap Internet, who have partnered with Zend to offer PHP training.

How do I fix an error that PHP finds in my script?

There you are, half way through your latest and greatest script, and all of a sudden a test execution delivers this error:

Parse error: parse error, unexpected T_ECHO, expecting ',' or ';'    
in c:htdocssitepointphpbasics2.php on line 5

The offending code here is as follows:

Example 1.2. 2.php

<?php    
echo 'This is some code<br />';    
echo 'Somewhere in here I've got a ';    
echo 'parse error!<br />'    
echo 'But where is it?<br />';    
?>

What you're dealing with here is known as a syntax error, and while you're new to PHP you may find yourself spending a lot of time hunting down such problems. As you get more experienced with PHP, tracking down syntax errors will become easier. You'll even come to know your own bad habits and probably be able to guess the error you made before you start the hunt (my own typical failings are forgetting the final quote when building SQL statements in a PHP string and leaving out commas when building arrays). Being familiar with PHP's error messages is a good idea, though.

In general terms, there are four basic types of errors you'll encounter in your PHP applications:

Syntax Errors

As in the example above, syntax errors occur when you break the rules of PHP's syntax. Syntax errors will usually result in a Parse Error message from PHP.

In the example above, the problem itself occurs on line 4:

echo 'parse error!<br />'

I forgot to add at the end of the line the semicolon (;) that's required to mark the termination of every statement. The PHP parser only noticed the problem on line five when it encountered another echo statement, as instructions may legally span more than one line. This is worth being aware of, as it sometimes makes errors hard to find - an error might actually have occurred prior to the line on which PHP noticed a problem.

Syntax errors can get particularly confusing in the case of large if-else or while statements where, for example, you've forgotten a closing parenthesis. Perhaps you have a long listing that's interspersed by blocks of HTML; finding that missing curly brace may be extremely difficult. However, as your coding technique improves and you start to take advantage of classes, breaking your code up into discrete blocks within which the code is short and easy to read, you'll find locating syntax errors much easier.

One further thing to be aware of is PHP's use of tokens. In the above error message, PHP complained about an "unexpected T_ECHO." A T_ECHO is a token representing an echo statement in your PHP script. The PHP parser breaks your code up into tokens so that it can analyze and process the script. Some of the tokens you'll see reported in parse errors are less obvious than others, so if you're unsure, it's worth looking at the manual on tokens.

If you're using PHP 4.3.0, you'll find it includes the so-called tokenizer extension, which allows you to see your script the way the PHP parser views it. For the sake of interest, here's how you could view the tokenizer's output:

Example 1.3. 3.php

<?php    
/* Note: This script will only work with PHP 4.3.0 or later */    
   
// Read a PHP script as a string    
$script = file_get_contents('2.php');    
   
// Fetch the tokens into an array    
$tokens = token_get_all($script);    
   
// Display    
echo '<pre>';    
print_r($tokens);    
echo '</pre>';    
?>

Semantic Errors

Semantic errors occur when you write code that obeys the rules of PHP's syntax, but which, when executed, breaks the "runtime rules" of PHP. For example, the foreach statement expects you to give it an array:

Example 1.4. 4.php

<?php    
$variable = 'This is not an array';    
   
foreach ($variable as $key => $value) {    
 echo $key . ' : ' . $value;    
}    
?>

Because $variable was not an array, this script produces the following error message:

Warning: Invalid argument supplied for foreach() in    
c:htdocssitepointphpbasics3.php on line 4

Semantic errors usually result in a Warning error message like this one.

Environment Errors

Environment errors occur when a system that's external to a PHP script causes a problem. For example, your MySQL server might have been down at the point at which your PHP script tried to connect to it. Perhaps you specified an incorrect path to a file you wanted to open, so PHP was unable to find the file.

These errors also occur when we take a PHP script that has been written on one system, and execute it on another system with a different environment. The problem may simply be that the underlying directory structure or domain name of the Web server is different. It's common to deal with these types of issues by creating a central configuration script that stores all these environment variables.

PHP also has a number of settings in php.ini that can cause a script to fail on another system where the settings are different. I'll be looking at these in the section called "How do I write portable PHP code?"; there's also summary information in Appendix A, PHP Configuration.

Logic Errors

Logic errors occur when an application runs perfectly as far as the PHP engine is concerned, but the code does something other than what you had intended. For example, imagine you have a mailing script that you want to use to send the same message to a few of the members of your online forum. To your horror, you discover upon executing the script that you've mailed the entire forum membership ... twenty times!

These kinds of problems are the most difficult to find; users of Windows XP will be well acquainted with Windows updates - even big companies struggle with logic errors.

Critical to finding logic errors is your ability to test rigorously your code in a safe environment that's separate from your "live" Web server. Thankfully, PHP and related technologies like Apache and MySQL (if you're using them) are cross platform, which makes putting together an effective development environment easy even if the underlying operating systems are different.

You should also investigate unit testing, a facet of Extreme Programming (XP), to which you'll find an introduction in Chapter 6, Development Technique. I've also suggested further reading at the end of this chapter.

In Chapter 10, Error Handling, I'll be taking a look at strategies for handling errors themselves, particularly environment errors. In particular, we'll discuss how you can record (or trap) errors for your analysis without displaying ugly messages to your applications users.

How do I include one PHP script in another?

Having discovered that writing thousand-line scripts may not be the best way to stay organized, you're probably looking for ways to break your code into separate files. Perhaps, while using someone else's Open Source application, you find yourself struggling to eliminate error messages like the one below:

Fatal error: Failed opening required 'script.php'

Mutual Inclusion

PHP provides four commands that allow you to add the contents of one PHP script to another, namely include, require, include_once and require_once. In each case, PHP fetches the file named in the command, then executes its contents. The difference between include and require is the way they behave should they be unable to find the script they were told to fetch.

include will generate a PHP warning message like this:

Warning: Failed opening 'script.php' for inclusion

This will allow the script that called the include command to continue execution.

By contrast, require results in a fatal error like the one shown above, which means the calling script will terminate, bringing everything to a halt. If the file that was required is critical to your application, having the script terminate is a very good thing.

The include_once and require_once commands behave similarly to their respective cousins, but if the script has already been included or required anywhere else (by any of the four commands), the statement will be ignored. At first glance, it may not be obvious how these commands can be used; surely you'll know how many times you've used an include command, right? Where the _once commands become extremely handy is in more complex applications in which you have PHP scripts that include other PHP scripts, which in turn include yet more PHP scripts. This is particularly important when you use libraries of classes (which we'll explore in Chapter 2, Object Oriented PHP), and those classes are being reused repeatedly by many scripts. One class may depend on another being available; using a require_once to include the required class ensures it will always be available, yet causes no problem if the class happens to have been used elsewhere.

To see all this in action, let's make a script called include_me.php:

Example 1.5. include_me.php

<?php     
// include_me.php    
   
echo 'I've been included!<br />';    
?>

Every time this script is included it will display the message "I've been included!" so we know it's worked.

Now, let's test the various ways we can include this file in another script:

Example 1.6. 5.php

<?php     
// This works fine    
echo '<br />Requiring Once: ';    
require_once 'include_me.php';    
   
// This works fine as well    
echo '<br />Including: ';    
include 'include_me.php';    
   
// Nothing happens as file is already included    
echo '<br />Including Once: ';    
include_once 'include_me.php';    
   
// This is fine    
echo '<br />Requiring: ';    
require 'include_me.php';    
   
// Again nothing happens - the file is included    
echo '<br />Requiring Once again: ';    
require_once 'include_me.php';    
   
// Produces a warning message as the file doesn't exist    
echo '<br />Include the wrong file: ';    
include 'include_wrong.php';    
   
// Produces a fatal error and script execution halts    
echo '<br />Requiring the wrong file: ';    
require 'include_wrong.php';    
   
// This will never be executed as we have a fatal error    
echo '<br />Including again: ';    
include 'include_me.php';    
?>

Here's the output this generates (note that I've simplified the error messages at the end):

Requiring Once: I've been included!     
   
Including: I've been included!    
   
Including Once:    
   
Requiring: I've been included!    
   
Requiring Once again:    
   
Include the wrong file:    
Warning: Failed opening 'include_wrong.php' for inclusion    
   
Requiring the wrong file:Fatal error: Failed opening required    
'include_wrong.php'

Notice here that the first use of include_once does nothing (the file has already been included), as does the later use of require_once. Later on, when I try to include the wrong file (in this case, a file that doesn't exist), I get a warning message. However, execution continues to the next line where I try to require a file that doesn't exist. This time, PHP produces a fatal error and execution of the script halts, meaning the final attempt to include the file will never happen.

Be aware that the files you include needn't contain only PHP. The included file could simply contain HTML without any PHP.

Which Command to Use?

As a general practice, unless you have a special circumstance where some other behavior is needed, always use the require_once command to include one file in another. This is particularly important when you're placing PHP classes in separate files, and one class may depend on another. For the full story on classes, see Chapter 2, Object Oriented PHP.

PHP's four include commands should not be confused with the various file-related functions (discussed in Chapter 4, Files); these are intended for fetching files without parsing them immediately as PHP scripts, thereby allowing you to work on their contents.

Note that throughout this book I'll be talking about "including" a file even when I'm using one of the require commands. This is a common convention for talking about PHP that stems from older programming languages used by the first PHP pioneers.

Path Finding

So far, I've only looked at including files in the same directory as the script that contains the include command. In practice, you'll usually want to organize files into subdirectories based on the job they do. This can be a source of much confusion, particularly when you're using third party code, as there are numerous alternative approaches to dealing with includes in other directories.

The first thing to be aware of is that all includes are calculated relative to the directory in which the main script (where execution began) resides. For example, imagine we have three files in the following locations:

/home/username/www/index.php     
/home/username/www/includes/script.php    
/home/username/www/another.php

First, let's consider index.php. The command include 'includes/script.php'; will correctly include script.php, assuming index.php is the actual file requested.

But what if we use the following command in script.php:

include '../another.php'; // ???

If script.php is the page we're viewing, this command will correctly include another.php. However, if index.php is the page we're viewing, and it includes script.php, this command will fail, because the location of another.php is calculated relative to the location of index.php, not relative to script.php.

We have two choices. We can modify script.php so that it includes another.php as follows:

include 'another.php';

Alternatively, we can enter the full path to another.php, like this:

include '/home/username/www/another.php';

This leaves no doubt as to where another.php is located.

The PHP configuration file php.ini also contains the directive include_path. This allows you to specify directories from which files can be included, without the need to specify their locations when using one of the include commands.

This approach needs to be used with caution, as it may lead to strange results if an included file of the same name exists in more than one directory, yet it can be an effective means to solve include-related headaches. PHP's PEAR class library, for example, relies on your adding the directory that contains PEAR's include files to the include path. Note also that it's not a good idea to specify too many locations in your include path, as this will slow PHP down when it tries to find the scripts you've included in your code.

If you're using Apache in a shared hosting environment, you may be able to override the value of include_path using a .htaccess file. Placed in the directory to which you want it to apply (it will also apply to all subdirectories), the file should contain something like this:

php_value include_path ".:/usr/local/lib/php:/home/user/phplib/"

The same can also be accomplished with the PHP function ini_set, for example:

ini_set('include_path', 'C:/phplib/');

This allows changes to be made at runtime from within a PHP script.

You'll find a reference to php.ini values in Appendix A, PHP Configuration.

How do I write portable PHP code?

Not all PHP installations are the same. Depending on version and configuration settings in php.ini, your script may or may not run correctly on another server where PHP is installed. However, there are some general good practices you can adopt to make life easier and minimize the need to rewrite code for other servers.

Keep All Configuration Central

For most PHP applications, it will be necessary to provide information describing the environment in which the script will run, including database user names and passwords, directory locations, and so on. As a general rule, try to keep the majority of this information in a single place - maybe even a single file - so that when the information needs to be modified, you can do it all in the one place. That said, when building modular applications, you may want to store elements of the configuration that are local to a specific "module" with the module itself, rather than centrally.

How exactly you choose to store this information is a matter of personal choice. In some cases, it may be worth considering an XML file or storing some of the information in a database. It's also worth being aware of the parse_ini_file function, which I'll explore in Chapter 4, Files.

A simple but effective mechanism is to place all the settings in a single file as PHP constants, which makes them available from any function or class in your application. For example:

Example 1.7. 6.php

<?php      
// Configuration settings      
define('DOMAIN', 'sitepoint.com');      
     
// In another script      
echo 'The domain is ' . DOMAIN;      
?>

Constants need to be used with caution, though. To make your functions and classes reusable in other applications, they shouldn't depend on constants of a fixed name; rather, they should accept configuration information as arguments. In such cases, it's best to use PHP variables in your central configuration file, which you can then pass to functions and classes as required. If you look at Chapter 3, PHP and MySQL, when connecting to MySQL we can identify a number of variables we need to have in a central location: the server host name, the user name, the password, and the name of the selected database.

Using the require_once command we looked at in the previous solution, we can create a file called, for instance, config.php, and place it outside the public Web directories. This helps ensure that no one accidentally browses to the file containing this critical information, which would place the site's security at risk.

Use the Full <?php ?> Tags

PHP supports a variety of tag styles to mark up sections of PHP code, including the short tags (<? ?>), and ASP-style tags (<% %>). These are controlled from php.ini with the settings short_open_tag and asp_tags. While you have these settings set to On, other people may not. The short tag style, for example, causes a problem when the PHP is mixed with XML documents, which use processing instructions like this:

<?xml version="1.0"?>

If we have a document which contains PHP and XML, and we have the short_open_tag turned on, PHP will mistake the XML processing instruction <?xml for a PHP opening tag.

It's possible that your code will need to run in environments where short_open_tags and asp_tags are both off. The best way to be sure that they are is to get into the habit of always using the <?php ?> tag style, otherwise there may be a lot of code rewriting to do in some dark future.

register_globals off

PHP is capable of turning incoming data into native PHP variables. This feature is controlled by the register_globals setting in php.ini. With register_globals switched on, if I point my browser at an address like http://www.mysite.com/index.php?logged_in=1, PHP will automatically create a variable $logged_in and assign it the value of 1. The PHP group now recommends this setting be disabled because it presents a risk to security, as the previous example suggests.

So, in php.ini make sure the following code is in place:

register_globals = Off

This will force you to access incoming data via the special predefined superglobal variables (e.g. $_GET['username']), which means they won't conflict with variables you've created in your script.

Using a .htaccess file with Apache, the same result can be achieved with the following code:

php_flag register_globals off

Further information can be found in the PHP manual, and in Kevin Yank's article, Write Secure Scripts with PHP 4.2! on SitePoint.

Magic Quotes

Magic quotes is a feature intended to help prevent security breaches in sites developed by PHP beginners.

It adds escape characters (see Chapter 5, Text Manipulation for more information) to incoming URL query strings, form posts, and cookie data automatically, before your script is able to access any of these values. Should you insert the data directly into your database, there's no risk of someone being able to tamper with the database provided magic quotes functionality is switched on.

For beginners, this is certainly a useful way to prevent disasters. However, once you understand what SQL injection attacks are, and have developed the habit of dealing with them in your code, the magic quote functionality can become more of a problem than it's worth.

Magic quotes functionality is controlled by a PHP configuration setting, magic_quotes_gpc, which can be either on or off.

My own preference is to always have magic quotes switched off, and deal with escaping data for SQL statements myself. Unfortunately, this means the code I write won't port well to PHP installations where magic quotes is switched on (I'll end up with backslashes in my content). Thankfully, to deal with this problem, PHP provides the function get_magic_quotes_gpc, which can be used to find out whether magic quotes are switched on. To keep the code in this book portable, we'll use a simple file that strips out magic quotes, should the functionality be enabled:

Example 1.8. MagicQuotes/strip_quotes.php (in SPLIB)

<?php       
/**      
* Checks for magic_quotes_gpc = On and strips them from incoming      
* requests if necessary      
*/      
if (get_magic_quotes_gpc()) {      
 $_GET    = array_map('stripslashes', $_GET);      
 $_POST   = array_map('stripslashes', $_POST);      
 $_COOKIE = array_map('stripslashes', $_COOKIE);      
}      
?>

If we include this at the start of any file in which we accept data from a query string, a form post, or a cookie, we'll remove any slashes added by magic quotes, should this functionality be switched on. This effectively gives us back what we started with.

The subject of SQL injection attacks is discussed in detail in the section called "How do I solve database errors caused by quotes/apostrophes?". If you're not yet confident that you can protect yourself against SQL Injection attacks, use magic quotes. Once you're happy you have a full grasp of all the issues, switch the magic quotes functionality off and save yourself many headaches. Note that magic quotes can only be switched on or off using the php.ini file or one of Apache's .htaccess files. For more information, see Appendix A, PHP Configuration.

Call-Time Pass-By-Reference Off

A reference is like a "short cut" to the value of a variable. References are often required when we use PHP functions and classes, a subject we'll discuss further in Chapter 2, Object Oriented PHP. When you use a reference to a variable in calling a function or class method, it's defined as a call-time pass-by-reference Consider this example:

$result = myFunction(&$myVariable);

Here the & operator tells PHP to use a reference to the variable $myVariable as the argument, rather than creating a copy of its value. This is now generally regarded as bad practice, as it can make the job of understanding someone else's code extremely difficult.

Switch this off in php.ini using the following command:

allow_call_time_pass_reference = Off

Alternatively, switch it off in a .htaccess file as follows:

php_flag allow_call_time_pass_reference off

Write Reusable Code

It's easy to say, I know, but if you find yourself writing any more than one PHP script, you need to start thinking about ways to make your code reusable, before you suffer premature hair loss. Technically, this isn't exactly an issue of portability as such, but if you end up working on other sites or applications, you'll appreciate having ready code that you can simply plug into your new project. Also, if you're writing code that other people will integrate with existing applications on their Websites, you need to package it in a form that doesn't place requirements on the code they're already using.

For example, if your application has some kind of user authentication system, will it integrate with the one they're already using - a system that already has a large database of users associated with it?

The best approach is to write object oriented code (the focus of Chapter 2, Object Oriented PHP) with a mind to creating reusable "components." Some people argue that writing object oriented code in PHP slows down the application's performance and should therefore be avoided at all costs. What they forget to mention is the drastic increase in your performance that object oriented programming delivers. After all, fast programmers cost more than fast microprocessors!

Some things to consider when measuring the potential of your code for reuse are:

  • What happens when requirements change?
  • How easy is it to add new features to your code?
  • Are you still able to understand the code after a long period of time?
  • Can your code be integrated easily with other applications?
  • Will assumptions made in your code apply to your work on other sites?

You'll find throughout this book many hints and suggestions to encourage you to write reusable code, although an in-depth analysis of PHP applications design as a whole is beyond its scope. As you read this book, you should get a feeling for some of the critical factors as subjects for further investigation. You have one main responsibility to yourself as an experienced PHP developer: to keep expanding your general knowledge of the more esoteric aspects of software development, such as design patterns and enterprise application architecture, as a means to improve your development technique and, more importantly, save yourself time. The broader your knowledge, the lower the risk of failure when you land that big project.

Further Reading

Look out for more chapters from The PHP Anthology on SitePoint in coming weeks! If you can't wait, download the sample chapters, or order your very own copy now!

Free book: Jump Start HTML5 Basics

Grab a free copy of one our latest ebooks! Packed with hints and tips on HTML5's most powerful new features.

No Reader comments

Comments on this post are closed.