PHP Solutions: Dynamic Web Design Made Easy, Third Edition (2014)

Chapter 3. How to Write PHP Scripts

If you run screaming at the sight of code, this is the chapter you’ll enjoy the least, but it’s an important one that I’ve tried to make as user friendly as possible. The chapter is in two parts: the first section offers a quick overview of how PHP works and gives you the basic rules; the second section goes into more detail.

You can read just the first section and come back to the more detailed parts later, or you can read the chapter straight through. However, don’t attempt to memorize everything at one sitting. The best way to learn is by doing. Coming back to the second part of the chapter for a little information at a time is likely to be more effective.

If you’re already familiar with PHP, you may want to skim through the main headings to see what this chapter contains and brush up your knowledge on any aspects that you’re a bit hazy about.

This chapter covers:

·     Understanding how PHP is structured

·     Embedding PHP in a webpage

·     Storing data in variables and arrays

·     Getting PHP to make decisions

·     Looping through repetitive tasks

·     Using functions for preset tasks

·     Understanding PHP objects and classes

·     Displaying PHP output

·     Understanding PHP error messages

PHP: The Big Picture

At first glance, PHP code can look quite intimidating, but once you understand the basics, you’ll discover that the structure is remarkably simple. If you have worked with any other computer language, such as JavaScript or jQuery, you’ll find they have a lot in common.

Every PHP page must have the following:

·     The correct filename extension, usually .php

·     Opening and closing PHP tags surrounding each block of PHP code (although the closing PHP tag can be omitted if the file contains only PHP code)

A typical PHP page will use some or all of the following elements:

·     Variables to act as placeholders for unknown or changing values

·     Arrays to hold multiple values

·     Conditional statements to make decisions

·     Loops to perform repetitive tasks

·     Functions or objects to perform preset tasks

Let’s take a quick look at each of these in turn, starting with the filename and the opening and closing tags.

Telling the Server to Process PHP

PHP is a server-side language. This means that the web server processes your PHP code and sends only the results—usually as HTML—to the browser. Because all the action is on the server, you need to tell it that your pages contain PHP code. This involves two simple steps, namely:

·     Give every page a PHP filename extension; the default is .php. Do not use anything other than .php unless you are specifically told to do so by your hosting company.

·     Enclose all PHP code within PHP tags.

The opening tag is <?php and the closing tag is ?>. If you put the tags on the same line as surrounding code, there doesn’t need to be a space before the opening tag or after the closing one, but there must be a space after the php in the opening tag like this:

<p>This is HTML with embedded PHP<?php //some PHP code ?>.</p>

When inserting more than one line of PHP, it’s a good idea to put the opening and closing tags on separate lines for the sake of clarity.

<?php
// some PHP code
// more PHP code
?>

You may come across <? as an alternative short version of the opening tag. However, <? doesn’t work on all servers. Stick with <?php, which is guaranteed to work.

Image Note  To save space, most examples in this book omit the PHP tags. You must always use them when writing your own scripts or embedding PHP into a webpage.

Embedding PHP in a Webpage

PHP is an embedded language. This means that you can insert blocks of PHP code inside ordinary webpages. When somebody visits your site and requests a PHP page, the server sends it to the PHP engine, which reads the page from top to bottom looking for PHP tags. HTML passes through untouched, but whenever the PHP engine encounters a <?php tag, it starts processing your code and continues until it reaches the closing ?> tag. If the PHP code produces any output, it’s inserted at that point.

Image Tip  A page can have multiple PHP code blocks, but they cannot be nested inside each other.

Figure 3-1 shows a block of PHP code embedded in an ordinary webpage and what it looks like in a browser and in a page-source view after it has been passed through the PHP engine. The code calculates the current year, checks whether it’s different from a fixed year (represented by$startYear in line 26 of the code on the left of the figure), and displays the appropriate year range in a copyright statement. As you can see from the page-source view at the bottom right of the figure, there’s no trace of PHP in what’s sent to the browser.

9781484206362_Fig03-01.jpg

Figure 3-1. The PHP code remains on the server; only the output is sent to the browser

Image Tip  PHP doesn’t always produce direct output for the browser. It may, for instance, check the contents of form input before sending an email message or inserting information into a database. Therefore, some code blocks are placed above or below the main HTML code, or in external files. Code that produces direct output, however, always goes where you want the output to be displayed.

Storing PHP in an External File

As well as embedding PHP in HTML, it’s common practice to store frequently used code in separate files. When a file contains only PHP code, the opening <?php tag is mandatory, but the closing ?> tag is optional. In fact, the recommended practice is to leave out the closing PHP tag. However, you must use the closing ?> tag if the external file contains HTML after the PHP code.

Using Variables to Represent Changing Values

The code in Figure 3-1 probably looks like an awfully long-winded way to display a range of years. Surely it’s much simpler to just type out the actual dates? Yes, it is, but the PHP solution saves you time in the long run. Instead of your needing to update the copyright statement every year, the PHP code does it automatically. You write the code once and forget it. What’s more, as you’ll see in the next chapter, if you store the code in an external file, any changes to the external file are reflected on every page of your site.

This ability to display the year automatically relies on two key aspects of PHP: variables and functions. As the name suggests, functions do things; they perform preset tasks, such as getting the current date and converting it into human-readable form. I’ll cover functions a little later, so let’s work on variables first. The script in Figure 3-1 contains two variables: $startYear and $thisYear.

Image Tip  A variable is simply a name that you give to something that may change or that you don’t know in advance. Variables in PHP always begin with $ (a dollar sign).

Although the concept of variables sounds abstract, we use variables all the time in everyday life. When you meet somebody for the first time, one of the first things you ask is “What’s your name?” It doesn’t matter whether the person you’ve just met is Tom, Dick, or Harry, the word “name” remains constant. Similarly, with your bank account, money goes in and out all of the time (mostly out, it seems), but as Figure 3-2 shows, it doesn’t matter whether you’re scraping the bottom of the barrel or as rich as Croesus, the amount available is always referred to as the balance.

9781484206362_Fig03-02.jpg

Figure 3-2. The balance on your bank statement is an everyday example of a variable—the name stays the same, even though the value may change from day to day

So, “name” and “balance” are everyday variables. Just put a dollar sign in front of them and you have two ready-made PHP variables, like this:

$name
$balance

Simple.

Naming Variables

You can choose just about anything you like as the name for a variable, as long as you keep the following rules in mind:

·     Variables always begin with a dollar sign ($).

·     The first character after the dollar sign cannot be a number.

·     No spaces or punctuation marks are allowed, except for the underscore (_).

·     Variable names are case-sensitive: $startYear and $startyear are not the same.

When choosing names for variables, it makes sense to choose something that tells you what it’s for. The variables you’ve seen so far—$startYear, $thisYear, $name, and $balance—are good examples. Because you can’t use spaces in variable names, it’s a good idea to capitalize the first letter of the second or subsequent words when combining them (sometimes called camel case). Alternatively, you can use an underscore ($start_year, $this_year, etc.).

Technically speaking, you can use an underscore as the first character after the dollar sign, but it’s not recommended. PHP predefined variables (e.g., the superglobal arrays described a little later in this chapter) begin with an underscore, so there’s a danger that you may accidentally choose the same name and cause problems for your script.

Don’t try to save time by using really short variables. Using $sy, $ty, $n, and $b instead of the more descriptive ones makes code harder to understand—and that makes it hard to write. More important, it makes errors more difficult to spot. As always, there are exceptions to a rule. By convention, $i, $j, and $k are frequently used to keep count of the number of times a loop has run, and $e is used in error checking. You’ll see examples of these later in this chapter.

Image Caution  Although you have considerable freedom in the choice of variable names, you can’t use $this, because it has a special meaning in PHP object-oriented programming. It’s also advisable to avoid using any of the keywords listed athttp://php.net/manual/en/reserved.php.

Assigning Values to Variables

Variables get their values from a variety of sources, including the following:

·     User input through online forms

·     A database

·     An external source, such as a news feed or XML file

·     The result of a calculation

·     Direct inclusion in the PHP code

Wherever the value comes from, it’s always assigned with an equal sign (=), like this:

$variable = value;

The variable goes on the left of the equal sign, and the value goes on the right. Because it assigns a value, the equal sign is called the assignment operator.

Image Caution  Familiarity with the equal sign from childhood makes it difficult to get out of the habit of thinking that it means “is equal to.” However, PHP uses two equal signs (==) to signify equality. This is a major cause of beginner mistakes, and it often catches more experienced developers, too. The difference between = and == is covered in more detail later in this chapter.

Ending Commands With a Semicolon

PHP is written as a series of commands or statements. Each statement normally tells the PHP engine to perform a particular action, and it must always be followed by a semicolon, like this:

<?php
do this;
now do something else;
?>

As with all rules, there is an exception: you can omit the semicolon if there’s only one statement in the code block. However, don’t do it. Unlike JavaScript, PHP won’t automatically assume there should be a semicolon at the end of a line if you leave it out. This has a nice side effect: you can spread long statements over several lines and lay out your code for ease of reading. PHP, like HTML, ignores whitespace in code. Instead, it relies on semicolons to indicate where one command ends and the next one begins.

Image Tip  Using a semicolon at the end of a PHP statement (or command) is always right. A missing semicolon will bring your script to a grinding halt.

Commenting Scripts

PHP treats everything between the opening and closing PHP tags as statements to be executed unless you tell it not to do so by marking a section of code as a comment. The following three reasons explain why you may want to do this:

·     To insert a reminder of what the script does

·     To insert a placeholder for code to be added later

·     To disable a section of code temporarily

When a script is fresh in your mind, it may seem unnecessary to insert anything that isn’t going to be processed. However, if you need to revise the script several months later, you’ll find comments much easier to read than trying to follow the code on its own. Comments are also vital when you’re working in a team. They help your colleagues understand what the code is intended to do.

During testing, it’s often useful to prevent a line of code, or even a whole section, from running. PHP ignores anything marked as a comment, so this is a useful way of turning on and off code.

There are three ways of adding comments: two for single-line comments and one for comments that stretch over several lines.

Single-line Comments

The most common method of adding a single-line comment is to precede it with two forward slashes, like this:

// this is a comment and will be ignored by the PHP engine

PHP ignores everything from the double slashes to the end of the line, so you can also place comments alongside code (but only to the right):

$startYear = 2006; // this is a valid comment

Comments aren’t PHP statements, so they don’t end with a semicolon. But don’t forget the semicolon at the end of a PHP statement that’s on the same line as a comment.

An alternative style uses the hash or pound sign (#), like this:

# this is another type of comment that will be ignored by the PHP engine
$startYear = 2006; # this also works as a comment

Because # stands out prominently when several are used together, this style of commenting often indicates sections of a longer script, like this:

##################
## Menu section ##
##################

Multi-line Comments

For a comment to stretch over several lines, use the same style of comments as in Cascading Style Sheets (CSS) and JavaScript. Anything between /* and */ is treated as a comment, like this:

/* This is a comment that stretches
   over several lines. It uses the same
   beginning and end markers as in CSS. */

Multi-line comments are particularly useful when testing or troubleshooting, as they can be used to disable long sections of script without the need to delete them.

Image Tip  A combination of good comments and well-chosen variable names makes code easier to understand and maintain.

Using Arrays to Store Multiple Values

In common with other computing languages, PHP lets you store multiple values in a special type of variable called an array. A simple way of thinking about arrays is that they’re like a shopping list. Although each item might be different, you can refer to them collectively by a single name.Figure 3-3 demonstrates this concept: the variable $shoppingList refers collectively to all five items—wine, fish, bread, grapes, and cheese.

9781484206362_Fig03-03.jpg

Figure 3-3. Arrays are variables that store multiple items, just like a shopping list

Individual items—or array elements—are identified by means of a number in square brackets immediately following the variable name. PHP assigns the number automatically, but it’s important to note that the numbering always begins at 0. So the first item in the array, wine in our example, is referred to as $shoppingList[0], not $shoppingList[1]. And although there are five items, the last one (cheese) is $shoppingList[4]. The number is referred to as the array key or index, and this type of array is called an indexed array.

PHP uses another type of array in which the key is a word (or any combination of letters and numbers). For instance, an array containing details of this book might look like this:

$book['title'] = 'PHP Solutions: Dynamic Web Design Made Easy, Third Edition';
$book['author'] = 'David Powers';
$book['publisher'] = 'Apress';
$book['ISBN'] = '978-1-4842-0636-2';

This type of array is called an associative array. Note that the array key is enclosed in quotes (single or double, it doesn’t matter). It shouldn’t contain any spaces or punctuation, except for the underscore.

Arrays are an important and useful part of PHP. You’ll use them a lot, starting with the next chapter, when you’ll store details of images in an array to display a random image on a webpage. Arrays are also used extensively with databases as you fetch the results of a search in a series of arrays.

Image Note  You can learn the various ways of creating arrays in the second half of this chapter.

PHP’s Built-in Superglobal Arrays

PHP has several built-in arrays that are automatically populated with useful information. They are called superglobal arrays, and all begin with a dollar sign followed by an underscore. Two that you will see frequently are $_POST and $_GET. They contain information passed from forms through the Hypertext Transfer Protocol (HTTP) post and get methods, respectively. The superglobals are all associative arrays, and the keys of $_POST and $_GET are automatically derived from the names of form elements or variables in a query string at the end of a URL.

Let’s say you have a text input field called "address" in a form; PHP automatically creates an array element called $_POST['address'] when the form is submitted by the post method or $_GET['address'] if you use the get method. As Figure 3-4 shows,$_POST['address'] contains whatever value a visitor enters in the text field, enabling you to display it onscreen, insert it in a database, send it to your email inbox, or do whatever you want with it.

9781484206362_Fig03-04.jpg

Figure 3-4. You can retrieve the values of user input through the $_POST array, which is created automatically when a form is submitted using the post method

You’ll work with the $_POST array in Chapter 5 when you send the content of an online feedback form by email to your inbox. Other superglobal arrays that you’ll use in this book are $_SERVER, to get information from the web server in Chapters 4, 12, and 13, $_FILES to upload files to your website in Chapter 7, and $_SESSION, to create a simple login system in Chapters 9 and 17.

Image Caution  Don’t forget that PHP is case-sensitive. All superglobal array names are written in uppercase. $_Post or $_Get, for example, won’t work.

Understanding When to Use Quotes

If you look closely at the PHP code block in Figure 3-1, you’ll notice that the value assigned to the first variable isn’t enclosed in quotes. It looks like this:

$startYear = 2006;

Yet all the examples in “Using arrays to store multiple values” did use quotes, like this:

$book['title'] = 'PHP Solutions: Dynamic Web Design Made Easy, Third Edition';

The simple rules are as follows:

·     Numbers: No quotes

·     Text: Requires quotes

As a general principle, it doesn’t matter whether you use single or double quotes around text or a string, as text is called in PHP and other computer languages. The situation is actually a bit more complex than that, as explained in the second half of this chapter, because there’s a subtle difference in the way single and double quotes are treated by the PHP engine.

Image Note  The word “string” is borrowed from computer and mathematical science, where it means a sequence of simple objects—in this case, the characters in text.

The important thing to remember for now is that quotes must always be in matching pairs. This means you need to be careful about including apostrophes in a single-quoted string or double quotes in a double-quoted string. Take a look at the following line of code:

$book['description'] = 'This is David's latest book on PHP.';

At first glance, there seems to be nothing wrong with it. However, the PHP engine sees things differently than the human eye does, as Figure 3-5 demonstrates.

9781484206362_Fig03-05.jpg

Figure 3-5. An apostrophe inside a single-quoted string confuses the PHP engine

There are two ways around this problem:

·     Use double quotes if the text includes any apostrophes.

·     Precede apostrophes with a backslash (this is known as escaping).

So, either of the following is acceptable:

$book['description'] = "This is David's latest book on PHP.";
$book['description'] = 'This is David\'s latest book on PHP.';

The same applies with double quotes in a double-quoted string (although with the rules reversed). The following code causes a problem:

$play = "Shakespeare's "Macbeth"";

In this case, the apostrophe is fine, because it doesn’t conflict with the double quotes, but the opening quotes in front of Macbeth bring the string to a premature end. To solve the problem, either of the following is acceptable:

$play = 'Shakespeare\'s "Macbeth"';
$play = "Shakespeare's \"Macbeth\"";

In the first example, the entire string has been enclosed in single quotes. This gets around the problem of the double quotes surrounding Macbeth but introduces the need to escape the apostrophe in Shakespeare’s. The apostrophe presents no problem in a double-quoted string, but the double quotes around Macbeth both need to be escaped. So, to summarize:

·     Single quotes and apostrophes are fine inside a double-quoted string.

·     Double quotes are fine inside a single-quoted string.

·     Anything else must be escaped with a backslash.

Image Tip  The key is to remember that the outermost quotes must match. My preference is to use single quotes and to reserve double quotes for situations where they have a special meaning, as described in the second half of this chapter.

Special Cases: True, False, and Null

Although text should be enclosed in quotes, three special cases—true, false, and null—should never be enclosed in quotes unless you want to treat them as genuine text (or strings). The first two mean what you would expect; the last one, null, means “nothing” or “no value.”

Image Note  Technically speaking, true and false are Boolean values. This name comes from nineteenth-century mathematician George Boole, who devised a system of logical operations that subsequently became the basis of much modern-day computing. It’s a complicated subject, but you can find out more at http://en.wikipedia.org/wiki/Boolean_algebra. For most people, it’s sufficient to know that Boolean means true or false.

As the next section explains, PHP makes decisions on the basis of whether something equates to true or false. Putting quotes around false has surprising consequences. Take a look at the following code:

$OK = false;

It does exactly what you expect: it makes $OK false. Now, look at this:

$OK = 'false';

This does exactly the opposite of what you might expect: it makes $OK true! Why? Because the quotes around false turn it into a string, and PHP treats strings as true. (There’s a more detailed explanation in “The truth according to PHP” in the second half of this chapter.)

The other thing to note about true, false, and null is that they are case-insensitive. The following examples are all valid:

$OK = TRUE;
$OK = tRuE;
$OK = true;

So, to recap, PHP treats true, false, and null as special cases.

·     Don’t enclose them in quotes.

·     They are case-insensitive.

Making Decisions

Decisions, decisions, decisions. . . Life is full of decisions. So is PHP. They give it the ability to display different output according to circumstances. Decision-making in PHP uses conditional statements. The most common of these uses if and closely follows the structure of normal language. In real life, you may be faced with the following decision (admittedly not very often if you live in Britain): If the weather’s hot, I’ll go to the beach.

In PHP pseudo-code, the same decision looks like this:

if (the weather's hot) {
    I'll go to the beach;
}

The condition being tested goes inside parentheses, and the resulting action goes between curly braces. This is the basic decision-making pattern:

if (condition is true) {
    // code to be executed if condition is true
}

Image Tip  Conditional statements are control structures and are not followed by a semicolon. The curly braces keep together one or more individual statements that are intended to be executed as a group.

The code inside the curly braces is executed only if the condition is true. If it’s false, PHP ignores everything between the braces and moves on to the next section of code. How PHP determines whether a condition is true or false is described in the following section.

Sometimes, the if statement is all you need, but you often want a default action to be invoked if the condition isn’t met. To do this, use else, like this:

if (condition is true) {
    // code to be executed if condition is true
} else {
    // default code to run if condition is false
}

If you want more alternatives, you can add more conditional statements like this:

if (condition is true) {
    // code to be executed if condition is true
} else {
    // default code to run if condition is false
}
if (second condition is true) {
    // code to be executed if second condition is true
} else {
    // default code to run if second condition is false
}

In this case both conditional statements will be run. If you want only one code block to be executed, use elseif like this:

if (condition is true) {
    // code to be executed if first condition is true
} elseif (second condition is true) {
    // code to be executed if first condition fails
    // but second condition is true
} else {
    // default code if both conditions are false
}

You can use as many elseif clauses in a conditional statement as you like. Only the first condition that equates to true will be executed; all others will be ignored, even if they’re also true. This means you need to build conditional statements in the order of priority that you want them to be evaluated. It’s strictly a first-come, first-served hierarchy.

Image Note  Although elseif is normally written as one word, you can use else if as separate words.

An alternative decision-making structure, the switch statement, is described in the second half of this chapter.

Making Comparisons

Conditional statements are interested in only one thing: whether the condition being tested equates to true. If it’s not true, it must be false. There’s no room for half-measures or maybes. Conditions often depend on the comparison of two values. Is this bigger than that? Are they both the same? And so on.

To test for equality, PHP uses two equal signs (==), like this:

if ($status == 'administrator') {
    // send to admin page
} else {
    // refuse entry to admin area
}

Image Caution  Don’t use a single equal sign in the first line ($status = 'administrator'). Doing so opens the admin area of your website to everyone. Why? Because this automatically sets the value of $status to administrator; it doesn’t compare the two values. To compare values, you must use two equal signs. It’s a common mistake, but one with potentially disastrous consequences.

Size comparisons are performed using the mathematical symbols for less than (<) and greater than (>). Let’s say you’re checking the size of a file before allowing it to be uploaded to your server. You could set a maximum size of 50 KB like this (1 kilobyte = 1024 bytes):

if ($bytes > 51200) {
    // display error message and abandon upload
} else {
    // continue upload
}

Image Note  The second half of this chapter describes how to test for multiple conditions simultaneously.

Using Indenting and Whitespace for Clarity

Indenting code helps to keep statements in logical groups, making it easier to understand the flow of the script. There are no fixed rules; PHP ignores any whitespace inside code, so you can adopt any style you like. The important thing is to be consistent so that you can spot anything that looks out of place.

Most people find that indenting four or five spaces makes for the most readable code. Perhaps the biggest difference in styles lies in the way individual developers arrange curly braces. I put the opening curly brace of a code block on the same line as the preceding code, and put the closing brace on a new line after the code block, like this:

if ($bytes > 51200) {
    // display error message and abandon upload
} else {
    // continue upload
}

However, others prefer this style:

if ($bytes > 51200)
{
    // display error message and abandon upload
}
else
{
    // continue upload
}

The style isn’t important. What matters is that your code is consistent and easy to read.

Using Loops for Repetitive Tasks

Loops are huge timesavers because they perform the same task over and over again, yet involve very little code. They’re frequently used with arrays and database results. You can step through each item one at a time looking for matches or performing a specific task. Loops are particularly powerful in combination with conditional statements, allowing you to perform operations selectively on a large amount of data in a single sweep. Loops are best understood by working with them in a real situation. Details of all looping structures, together with examples, are in the second half of this chapter.

Using Functions for Preset Tasks

As I mentioned earlier, functions do things . . . lots of things, mind-bogglingly so in PHP. A typical PHP setup gives you access to several thousand built-in functions. Don’t worry: you’ll only ever need to use a handful, but it’s reassuring to know that PHP is a full-featured language.

The functions you’ll be using in this book do truly useful things, such as get the height and width of an image, create thumbnails from existing images, query a database, send email, and much, much more. You can identify functions in PHP code because they’re always followed by a pair of parentheses. Sometimes, the parentheses are empty, as in the case of phpversion(), which you used in phpversion.php in the previous chapter. Often, though, the parentheses contain variables, numbers, or strings, like this line of code from the script in Figure 3-1:

$thisYear = date('Y');

This code calculates the current year and stores it in the variable $thisYear. It works by feeding the string 'Y' to the built-in PHP function date(). Placing a value between the parentheses like this is known as passing an argument to a function. The function takes the value in the argument and processes it to produce (or return) the result. For instance, if you pass the string 'M' as an argument to date() instead of 'Y', it will return the current month as a three-letter abbreviation (e.g., Mar, Apr, May). As the following example shows, you capture the result of a function by assigning it to a suitably named variable:

$thisMonth = date('M');

Image Note  Chapter 14 covers in depth how PHP handles dates and time.

Some functions take more than one argument. When this happens, separate the arguments with commas inside the parentheses, like this:

$mailSent = mail($to, $subject, $message);

It doesn’t take a genius to work out that this sends an email to the address stored in the first argument, with the subject line stored in the second argument, and the message stored in the third one. You’ll see how this function works in Chapter 5.

Image Tip  You’ll often come across the term “parameter” in place of “argument.” Technically speaking, parameter refers to a variable used in the function definition, while argument refers to an actual value passed to the function. In practice, both terms tend to be used interchangeably.

As if all the built-in functions weren’t enough, PHP lets you build your own custom functions. Even if you don’t relish the idea of creating your own, throughout this book you’ll use some that I have made. You use them in exactly the same way.

Understanding PHP Classes and Objects

Functions and variables give PHP tremendous power and flexibility, but classes and objects take the language to an even higher level. Classes are the fundamental building blocks of object-oriented programming (OOP), an approach to programming that’s designed to make code reusable and easier to maintain. PHP has extensive support for OOP, and new features are frequently implemented in an object-oriented manner.

An object is a sophisticated data type that can store and manipulate values. A class is the code that defines an object’s features and can be regarded as a blueprint for making objects. Among PHP’s many built-in classes, two of particular interest are the DateTime and DateTimeZoneclasses, which deal with dates and time zones. Two other built-in classes that you’ll use in this book are MySQLi and PDO, which are used for communicating with databases.

To create an object, you use the new keyword with the class name like this:

$now = new DateTime();

This creates an instance of the DateTime class and stores it in a DateTime object called $now. What distinguishes this from the date() function in the preceding section is that a DateTime object is aware not only of the date and time it was created but also of the time zone used by the web server. The date() function, on the other hand, simply generates a number or string containing the date formatted according to the arguments passed to it.

In the preceding example, no arguments were passed to the class, but classes can take arguments in the same way that functions do, as you’ll see in the next example.

Most classes also have properties and methods, which are similar to variables and functions, except that they’re related to a particular instance of a class. For example, you can use the DateTime class’s methods to change certain values, such as the month, year, or time zone. ADateTime object is also capable of performing date calculations, which are much more complicated using ordinary functions.

You access an object’s properties and methods using the -> operator (a hyphen followed by a greater-than symbol). To reset the time zone of a DateTime object, pass a DateTimeZone object as an argument to the setTimezone() method like this:

$westcoast = new DateTimeZone('America/Los_Angeles');
$now->setTimezone($westcoast);

This resets the date and time stored in $now to the current date and time in Los Angeles, regardless of where the web server is located, automatically making any adjustments for daylight saving time.

The DateTime and DateTimeZone classes don’t have properties, but you access an object’s properties using the -> operator in the same way:

$someObject->propertyName

Don’t worry if you find the concepts of objects, properties, and methods difficult to grasp. All you need to know is how to instantiate objects with the new keyword and how to access properties and methods with the -> operator.

Image Tip  For an in-depth discussion of OOP in PHP with extensive hands-on examples, see my book PHP Object-Oriented Solutions (friends of ED, 2008, ISBN: 978-1-4302-1011-5).

Displaying PHP Output

There’s not much point in all this wizardry going on behind the scenes unless you can display the results in your webpage. There are two ways of doing this in PHP: using echo or print. There are some subtle differences between the two, but they are so subtle you can regard echo andprint as identical. I prefer echo for the simple reason that it’s one fewer letter to type.

You can use echo with variables, numbers, and strings; simply put it in front of whatever you want to display, like this:

$name = 'David';
echo $name;   // displays David
echo 5;       // displays 5
echo 'David'; // displays David

When using echo and print with a variable, they work only with variables that contain a single value. You cannot use them to display the contents of an array or of a database result. This is where loops are so useful: you use echo or print inside the loop to display each element individually. You’ll see plenty of examples of this in action throughout the rest of the book.

You may see scripts that use parentheses with echo and print, like this:

echo('David'); // displays David

The parentheses make no difference. Unless you enjoy typing for the sake of it, leave them out.

Using Echo Shortcut Syntax

When you want to display the value of a single variable or expression (and nothing else), you can use a shortcut opening PHP tag, which consists of an opening angle bracket, a question mark, and the equal sign, like this:

<p>My name is <?= $name; ?>.</p>

This produces exactly the same output as this:

<p>My name is <?php echo $name; ?>.</p>

Because it’s shorthand for echo, no other code can be in the same PHP block, but it’s particularly useful when embedding database results in a webpage. It goes without saying that the value of the variable must be set in a previous PHP block before you can use this shortcut.

Image Caution  Prior to PHP 5.4, the echo shortcut syntax worked only if the short_open_tag configuration setting was enabled in php.ini. Since PHP 5.4, <?= is always available.

Joining Strings Together

PHP has a rather unusual way of joining strings (text). Although many other computer languages use the plus sign (+), PHP uses a period, dot, or full stop (.), like this:

$firstName = 'David';
$lastName = 'Powers';
echo $firstName.$lastName; // displays DavidPowers

As the comment in the final line of code indicates, when two strings are joined like this, PHP leaves no gap between them. Don’t be fooled into thinking that adding a space after the period will do the trick. It won’t. You can put as much space on either side of the period as you like; the result will always be the same, because PHP ignores whitespace in code. In fact, it’s recommended to leave a space on either side of the period for readability.

To display a space in the final output, you must either include a space in one of the strings or insert the space as a string in its own right, like this:

echo $firstName . ' ' . $lastName; // displays David Powers

Image Tip  The period—or concatenation operator, to give it its correct name—can be difficult to spot among a lot of other code. Make sure the font size in your script editor is large enough to read without straining to see the difference between periods and commas.

Working With Numbers

PHP can do a lot with numbers, from simple addition to complex math. The second half of this chapter contains details of the arithmetic operators you can use with PHP. All you need to remember at the moment is that numbers must not contain any punctuation other than a decimal point. PHP will choke if you feed it numbers that contain commas (or anything else) as the thousands separator.

Understanding PHP Error Messages

Error messages are an unfortunate fact of life, so you need to understand what they’re trying to tell you. The following illustration shows a typical error message.

9781484206362_unFig03-01.jpg

PHP error messages report the line where PHP discovered a problem. Most newcomers—quite naturally—assume that’s where to look for their mistake. Wrong . . .

Most of the time, PHP is telling you that something unexpected has happened. In other words, the mistake lies before that point. The preceding error message means that PHP discovered an echo command where there shouldn’t have been one. (Error messages always prefix PHP elements with T_, which stands for token. Just ignore it.)

Instead of worrying what might be wrong with the echo command (probably nothing), start working backward, looking for anything missing, probably a semicolon or closing quote on a previous line.

Sometimes, the message reports the error on the last line of the script. That always means you have omitted a closing curly brace somewhere further up the page.

There are seven main categories of errors, presented here in descending order of importance:

·     Fatal error: Any HTML output preceding the error will be displayed, but once the error is encountered—as the name suggests—everything else is killed stone dead. A fatal error is normally caused by referring to a nonexistent file or function.

·     Recoverable error: This type of error occurs only when a particular type of error known as an exception is thrown. The error message contains much detail, explaining the cause and location of the problem, but it can be difficult for beginners to understand. To avoid recoverable errors, use try and catch blocks as described in the “Handling exceptions” section.

·     Parse error: This means there’s a mistake in your code syntax, such as mismatched quotes or a missing semicolon or closing brace. It stops the script in its tracks, and it doesn’t even allow any HTML output to be displayed.

·     Warning: This alerts you to a serious problem, such as a missing include file. (Include files are the subject of Chapter 4.) However, the error is not serious enough to prevent the rest of the script from being executed.

·     Deprecated: This warns you about features that are scheduled to be removed from a future version of PHP. If you see this type of error message, you should seriously consider updating your script, as it could suddenly stop working if your server is upgraded.

·     Strict: This type of error message warns you about using techniques that are not considered good practice.

·     Notice: This advises you about relatively minor issues, such as the use of a nondeclared variable. Although this type of error won’t stop your page from displaying (and you can turn off the display of notices), you should always try to eliminate them. Any error is a threat to your output.

Why is My Page Blank?

Many beginners are left scratching their heads when they load a PHP page into a browser and see absolutely nothing. There’s no error message, just a blank page. This happens when there’s a parse error—in other words, a mistake in the code—and the display_errors directive inphp.ini is turned off.

If you followed the advice in the previous chapter, display_errors should be enabled in your local testing environment. However, most hosting companies turn off display_errors. This is good for security, but it can make it difficult to troubleshoot problems on your remote server. As well as parse errors, a missing include file often causes blank pages.

You can turn on the display of errors for an individual script by adding the following code right at the top of the page:

ini_set('display_errors', '1');

Put this code on the first line after the opening PHP tag, or in a separate PHP block at the top of the page if the PHP is lower down the page. When you upload the page and refresh the browser, you should see any error messages generated by PHP.

If you still see a blank page after adding this line of code, it means there’s an error in your syntax. Test the page locally with display_errors turned on to find out what’s causing the problem.

Image Caution  After correcting the error, remove the code that turns on the display of errors. If something else breaks in the script at a later stage, you don’t want to expose potential vulnerabilities on your live website.

Handling Exceptions

PHP 5 introduced a new way of handling errors, common to many other programming languages, known as exceptions. When a problem arises, many built-in classes automatically throw an exception—or generate a special type of object that contains details of what caused the error and where it arose. You can also throw custom exceptions, using the keyword throw, like this:

if (error occurs) {
    throw new Exception('Houston, we have a problem');
}

The string inside the parentheses is used as the error message. Obviously, in a real script, you need to make the message more explicit. When an exception is thrown, you should deal with it in a separate code block called—appropriately enough—catch.

When using objects, wrap your main script in a block called try and put the error-handling code in a catch block. If an exception is thrown, the PHP engine abandons the code in the try block and executes only the code in the catch block. The advantage is that you can use thecatch block to redirect the user to an error page rather than displaying an ugly error message onscreen—or a blank screen if the display of error messages is turned off, as it should be on a live website.

Image Note  The try and catch blocks must always be used as a pair. You can’t have one without the other.

During the development stage, you should use the catch block to display the error message generated by the exception like this:

try {
    // main script goes here
} catch (Exception $e) {
    echo $e->getMessage();
}

This produces an error message that’s usually much easier to understand than the lengthy message generated by a recoverable error. In the case of the previous problem.” Although I advised you earlier to use example, it would output “Houston, we have a descriptive variable names, using$e for an exception is a common convention.

Image Tip  Congratulations if you’ve managed to read this far. You should now have sufficient knowledge to get started. The rest of this chapter goes into greater detail about individual aspects of writing PHP scripts. Rather than plowing straight on, I suggest you take a short break and then move on to the next chapter. Come back to the following reference section when you’ve gained some practical experience of working with PHP, as it will make much more sense then.

PHP: A Quick Reference

The following sections don’t attempt to cover every aspect of PHP syntax. For that, you should refer to the PHP documentation at http://php.net/manual/en/ or check out a more detailed reference book, such as Beginning PHP and MySQL: From Novice to Professional, Fourth Edition by W. Jason Gilmore (Apress, 2010, ISBN: 978-1-4302-3114-1).

Using PHP in an Existing Website

There is no problem mixing .html and .php pages in the same website. However, PHP code will normally be processed only in files that have the .php filename extension, so it’s a good idea to give the same extension to all your pages, even if they don’t all contain dynamic features. That way, you have the flexibility to add PHP to pages without breaking existing links or losing search engine rankings.

Data Types in PHP

PHP is what’s known as a weakly typed language. In practice, this means that, unlike some other computer languages (e.g., Java or C#), PHP doesn’t care what type of data you store in a variable.

Most of the time, this is very convenient, although you need to be careful with user input. You may expect a user to enter a number in a form, but PHP won’t object if it encounters a word instead. Checking user input carefully is one of the major themes of later chapters.

Even though PHP is weakly typed, it uses the following eight data types:

·     Integer: This is a whole number, such as 1, 25, 42, or 2006. Integers must not contain any commas or other punctuation as thousand separators. You can also use hexadecimal numbers, which should be preceded by 0x (e.g., 0xFFFFFF, 0x000000).

·     Floating-point number: This is a number that contains a decimal point, such as 9.99, 98.6, or 2.1. PHP does not support the use of the comma as the decimal point, as is common in many European countries. You must use a period. Like integers, floating-point numbers must not contain thousand-separators. (This type is also referred to as float or double.)

·     String: A string is text of any length. It can be as short as zero characters (an empty string) and has no upper limit.

·     Boolean: This type has only two values: true or false. However, PHP treats other values as implicitly true or false. See “The truth according to PHP” later in this chapter.

·     Array: An array is a variable capable of storing multiple values, although it may contain none at all (an empty array). Arrays can hold any data type, including other arrays. An array of arrays is called a multidimensional array. See “Creating arrays” later in this chapter for details of how to populate an array with values.

·     Object: An object is a sophisticated data type capable of storing and manipulating values. You’ll learn more about objects in Chapter 6.

·     Resource: When PHP connects to an external data source, such as a file or database, it stores a reference to it as a resource.

·     NULL: This is a special data type that indicates that a variable has no value.

An important side effect of PHP’s weak typing is that if you enclose an integer or floating-point number in quotes, PHP automatically converts it from a string to a number, allowing you to perform calculations without the need for any special handling. This is different from JavaScript, and it can have unexpected consequences. When PHP sees the plus sign (+), it assumes you want to perform addition, and thus it tries to convert strings to integers or floating-point numbers, as in the following example (the code is in data_conversion_01.php in the ch03 folder):

$fruit = '2 apples';
$veg = ' 2 carrots';
echo $fruit + $veg;  // displays 4

PHP sees that both $fruit and $veg begin with a number, so it extracts the number and ignores the rest. However, if the string doesn’t begin with a number, PHP converts it to 0, as shown in this example (the code is in data_conversion_02.php):

$fruit = '2 apples';
$veg = ' and 2 carrots';
echo $fruit + $veg;  // displays 2

Weak typing is a mixed blessing. It makes PHP very easy for beginners, but it means you often need to check that a variable contains the correct data type before using it.

Doing Calculations with PHP

PHP is highly adept at working with numbers and can perform a wide variety of calculations, from simple arithmetic to complex math. This reference section covers only the standard arithmetic operators. See http://php.net/manual/en/book.math.php for details of the mathematical functions and constants supported by PHP.

Image Note  A constant is similar to a variable in that it uses a name to represent a value. However, the value of a constant, once defined, cannot be changed. All PHP predefined constants are in uppercase. Unlike variables, they do not begin with a dollar sign. For example, the constant for π (pi) is M_PI.

Arithmetic Operators

The standard arithmetic operators all work the way you would expect, although some of them look slightly different from those you learned at school. For instance, an asterisk (*) is used as the multiplication sign, and a forward slash (/) is used to indicate division. Table 3-1 shows examples of how the standard arithmetic operators work. To demonstrate their effect, the following variables have been set:

$x = 20;
$y = 10;
$z = 3;

Table 3-1. Arithmetic operators in PHP

Table3-1

The modulus operator converts both numbers to integers by stripping the decimal portion before processing and returns the remainder of a division, as follows:

5 % 2.5    // result is 1, not 0 (the decimal fraction is stripped from 2.5)
10 % 2     // result is 0

Modulus is useful for working out whether a number is odd or even. $number % 2 always produces 0 or 1. If the result is 0, there is no remainder, so the number is even.

The increment (++) and decrement (--) operators can come either before or after the variable. When they come before the variable, 1 is added or subtracted before any further calculation is carried out. When they come after, the main calculation is carried out first, and then 1 is either added or subtracted. Since the dollar sign is an integral part of the variable name, the increment and decrement operators go before the dollar sign when used in front:

++$x
--$y

The exponentiation operator requires PHP 5.6 or later. Prior to PHP 5.6, use the pow() function, which takes two arguments: the base number and the exponent. For example, pow(10, 3) is equivalent to 10**3. Both raise 10 to the power of 3.

Determining the Order of Calculations

Calculations in PHP follow the same rules of precedence as standard arithmetic. Table 3-2 lists arithmetic operators in order of precedence, with the highest precedence at the top.

Table 3-2. Precedence of arithmetic operators

Group

Operators

Rule

Parentheses

()

Operations contained within parentheses are evaluated first. If these expressions are nested, the innermost is evaluated foremost.

Exponentiation

**

 

Increment/decrement

++ --

 

Multiplication and division

* / %

If an expression contains two or more of these operators, they are evaluated from left to right.

Addition and subtraction

+ -

If an expression contains two or more of these operators, they are evaluated from left to right.

Combining Calculations and Assignment

PHP offers a shorthand way of performing a calculation on a variable and reassigning the result to the variable through combined assignment operators. The main ones are listed in Table 3-3.

Table 3-3. Combined arithmetic assignment operators used in PHP

Operator

Example

Equivalent to

+=

$a += $b

$a = $a + $b

-=

$a -= $b

$a = $a - $b

*=

$a *= $b

$a = $a * $b

/=

$a /= $b

$a = $a / $b

%=

$a %= $b

$a = $a % $b

**=

$a **= $b

$a = $a ** $b

The combined exponentiation assignment operator (**=) is available only in PHP 5.6 and later.

Adding to an existing string

The same convenient shorthand allows you to add new material to the end of an existing string by combining a period and an equal sign, like this:

$hamlet = 'To be';
$hamlet .= ' or not to be';

Note that you need to create a space at the beginning of the additional text unless you want both strings to run on without a break. This shorthand, known as the combined concatenation operator, is extremely useful when combining many strings, such as is required when building the content of an email message or looping through the results of a database search.

Image Tip  The period in front of the equal sign is easily overlooked when copying code. When you see the same variable repeated at the beginning of a series of statements, it’s often a sure sign that you need to use .= instead of = on its own.

All You Ever Wanted to Know About Quotes—and More

Handling quotes within any computer language—not just PHP—can be fraught with difficulties because computers always take the first matching quote as marking the end of a string. Structured Query Language (SQL)—the language used to communicate with databases—also uses strings. Since your strings may include apostrophes, the combination of single and double quotes isn’t enough. Moreover, PHP gives variables and escape sequences (certain characters preceded by a backslash) special treatment inside double quotes. Over the next few pages, I’ll unravel this tangle and make sense of it all for you.

How PHP Treats Variables Inside Strings

Choosing whether to use double quotes or single quotes might just seem like a question of personal preference, but there’s an important difference in the way that PHP handles them.

·     Anything between single quotes is treated literally as text.

·     Double quotes act as a signal to process variables and special characters known as escape sequences.

In the following example, $name is assigned a value and then used in a single-quoted string. So $name is treated like normal text (the code is in quotes_01.php):

$name = 'Dolly';
echo 'Hello, $name';  // Hello, $name

If you replace the single quotes in the second line with double ones (see quotes_02.php), $name is processed and its value is displayed onscreen:

$name = 'Dolly';
echo "Hello, $name";  // Hello, Dolly

Image Note  In both examples, the string in the first line is in single quotes. What causes the variable to be processed is the fact that it’s in a double-quoted string, not how it originally got its value.

Because double quotes are so useful in this way, many people use them all the time. Technically speaking, using double quotes when you don’t need to process any variables is inefficient. My preference is to use single quotes unless the string contains variables.

Using Escape Sequences Inside Double Quotes

Double quotes have another important effect: they treat escape sequences in a special way. All escape sequences are formed by placing a backslash in front of a character. Most of them are designed to avoid conflicts with characters that are used with variables, but three of them have special meanings: \n inserts a new line character, \r inserts a carriage return, and \t inserts a tab. Table 3-4 lists the main escape sequences supported by PHP.

Table 3-4. The main PHP escape sequences

Escape sequence

Character represented in double-quoted string

\"

Double quote

\n

New line

\r

Carriage return

\t

Tab

\\

Backslash

\$

Dollar sign

\{

Opening curly brace

\}

Closing curly brace

\[

Opening square bracket

\]

Closing square bracket

Image Caution  With the exception of \\, the escape sequences listed in Table 3-4 work only in double-quoted strings. In a single-quoted string, they are treated as a literal backslash followed by the second character. A backslash at the end of the string always needs to be escaped. Otherwise, it’s interpreted as escaping the following quotation mark. In a single-quoted string, escape single quotes and apostrophes with a backslash as described in the first half of this chapter.

Embedding Associative Array Elements in a String

There’s a nasty “gotcha” with associative array elements in a double-quoted string. The following line of code attempts to embed a couple of elements from the $book associative array found in the first half of this chapter inside a double-quoted string:

echo "$book['title'] was written by $book['author'].";

It looks OK. The keys of the array elements use single quotes, so there’s no mismatch of quotes. Yet, if you load quotes_03.php into a browser, you get this enigmatic error message.

9781484206362_unFig03-02.jpg

The solution is simple. You need to enclose the associative array variables in curly braces like this (see quotes_04.php):

echo "{$book['title']} was written by {$book['author']}.";

The values are now displayed correctly, as shown in the following screenshot.

9781484206362_unFig03-03.jpg

Indexed array elements, such as $shoppingList[2], don’t need this special treatment because the array index is a number and is not enclosed in quotes.

Image Caution  Some people try to avoid the problem with associative array elements by removing the quotes from the array key, like this: $book[title]. Although it works, removing the quotes from the array key creates an undefined constant, which could result in your code breaking in the future.

Avoiding the Need to Escape Quotes with Heredoc Syntax

Using a backslash to escape one or two quotation marks isn’t a great burden, but I frequently see examples of code where backslashes seem to have run riot. It must be difficult to type, and it’s certainly difficult to read. Moreover, it’s totally unnecessary. The PHP heredoc syntax offers a relatively simple method of assigning text to a variable without any special handling of quotes.

Image Note  The name “heredoc” is derived from here-document, a technique used in Unix and Perl programming to pass large amounts of text to a command.

Assigning a string to a variable using heredoc involves the following steps:

1.    Type the assignment operator, followed by <<< and an identifier. The identifier can be any combination of letters, numbers, and the underscore, as long as it doesn’t begin with a number. The same combination is used later to identify the end of the heredoc.

2.    Begin the string on a new line. It can include both single and double quotes. Any variables will be processed in the same way as in a double-quoted string.

3.    Place the identifier on a new line after the end of the string. Nothing else should be on the same line, except for a final semicolon. Moreover, the identifier must be at the beginning of the line; it cannot be indented.

It’s a lot easier when you see it in practice. The following simple example can be found in heredoc.php in the files for this chapter:

$fish = 'whiting';
$book['title'] = 'Alice in Wonderland';
$mockTurtle = <<< Gryphon
"Will you walk a little faster?" said a $fish to a snail.
"There's a porpoise close behind us, and he's treading on my tail."
(from {$book['title']})
Gryphon;
echo $mockTurtle;

In this example, Gryphon is the identifier. The string begins on the next line, and the double quotes are treated as part of the string. Everything is included until you reach the identifier at the beginning of a new line.

Image Caution  Although heredoc syntax avoids the need to escape quotes, the associative array element $book['title'] still needs to be enclosed in braces, as described in the previous section.

As you can see from the following screenshot, the heredoc displays the double quotes and processes the $fish and $book['title'] variables.

9781484206362_unFig03-04.jpg

To achieve the same effect without using the heredoc syntax, you need to add the double quotes and escape them like this:

$mockTurtle = "\"Will you walk a little faster?\" said a $fish to a snail.
\"There's a porpoise close behind us, and he's treading on my tail.\" (from
{$book['title']})";

The heredoc syntax is mainly of value when you have a long string and/or lots of quotes. It’s also useful if you want to assign an XML document or a lengthy section of HTML to a variable.

Image Note  There’s a related technique called nowdoc syntax, which treats variables in the same way as single quotes—in other words, as literal text. To create a string using nowdoc syntax, enclose the identifier in single quotes like this: <<< 'Gryphon'. The closing identifier does not use quotes. See http://php.net/manual/en/language.types.string.php#language.types.string.syntax.nowdoc.

If you wrap the identifier in double quotes, the string is treated as heredoc syntax.

Creating Arrays

As explained earlier, there are two types of arrays: indexed arrays, which use numbers to identify each element, and associative arrays, which use strings. You can build both types by assigning a value directly to each element. Let’s take another look at the $book associative array:

$book['title'] = 'PHP Solutions: Dynamic Web Design Made Easy, Third Edition';
$book['author'] = 'David Powers';
$book['publisher'] = 'Apress';
$book['ISBN'] = '978-1-4842-0636-2';

To build an indexed array the direct way, use numbers instead of strings as the array keys. Indexed arrays are numbered from 0, so to build the $shoppingList array depicted in Figure 3-3, you would declare it like this:

$shoppingList[0] = 'wine';
$shoppingList[1] = 'fish';
$shoppingList[2] = 'bread';
$shoppingList[3] = 'grapes';
$shoppingList[4] = 'cheese';

Although both are perfectly valid ways of creating arrays, it’s a nuisance to have to type out the variable name each time; there are shorter ways of doing it. The syntax is slightly different for each type of array.

Building an Indexed Array

Since PHP 5.4, you have a choice of how to define an array in a single statement. The quick way is to use the shorthand syntax, which is the same as an array literal in JavaScript. You create the array by enclosing a comma-separated list of values between a pair of square brackets, like this:

$shoppingList = ['wine', 'fish', 'bread', 'grapes', 'cheese'];

Image Caution  The comma must go outside the quotes, unlike in American typographic practice. For ease of reading, I have inserted a space following each comma, but it’s not necessary to do so.

The alternative is to pass a comma-separated list to array(), like this:

$shoppingList = array('wine', 'fish', 'bread', 'grapes', 'cheese');

PHP numbers each array element automatically, beginning from 0, so both methods create exactly the same array as if you had numbered them individually. To add a new element to the end of the array, use a pair of empty square brackets, like this:

$shoppingList[] = 'coffee';

PHP uses the next number available, so this becomes $shoppingList[5].

Building an Associative Array

Associative arrays use the => operator (an equal sign followed by a greater-than sign) to assign a value to each array key. Using shorthand square-bracket syntax, the structure looks like this:

$arrayName = ['key1' => 'element1', 'key2' => 'element2'];

Using array() achieves the same outcome:

$arrayName = array('key1' => 'element1', 'key2' => 'element2');

So, this is the shorthand way to build the $book array:

$book = [
    'title'     => 'PHP Solutions: Dynamic Web Design Made Easy, Third Edition',
    'author'    => 'David Powers',
    'publisher' => 'Apress',
    'ISBN'      => '978-1-4842-0636-2'
];

It’s not essential to put the opening and closing brackets on separate lines, nor to align the => operators as I have done, but it makes code easier to read and maintain.

Creating an Empty Array

There are two reasons you might want to create an empty array, as follows:

·     To create (or initialize) an array so that it’s ready to have elements added to it inside a loop

·     To clear all elements from an existing array

To create an empty array, just use an empty pair of square brackets:

$shoppingList = [];

Alternatively, use array() with nothing between the parentheses, like this:

$shoppingList = array();

The $shoppingList array now contains no elements. If you add a new one using $shoppingList[], it will automatically start numbering again at 0.

Multidimensional Arrays

Array elements can store any data type, including other arrays. For instance, the $book array holds details of only one book. It might be more convenient to create an array of arrays—in other words, a multidimensional array—containing details of several books, like this (using square-bracket shorthand):

$books = [
    [
        'title'     => 'PHP Solutions: Dynamic Web Design Made Easy, Third Edition',
        'author'    => 'David Powers',
        'publisher' => 'Apress',
        'ISBN'      => '978-1-4842-0636-2'
    ],
    [
        'title'     => 'Beginning PHP and MySQL: From Beginner to Professional,
                        Fourth Edition',
        'author'    => 'W. Jason Gilmore',
        'publisher' => 'Apress',
        'ISBN'      => 978-1-4302-3114-1'
    ]
];

This example shows associative arrays nested inside an indexed array, but multidimensional arrays can nest either type. To refer to a specific element, use the key of both arrays; for example:

$books[1]['author']  // value is 'W. Jason Gilmore'

Working with multidimensional arrays isn’t as difficult as it first looks. The secret is to use a loop to get to the nested array. Then you can work with it in the same way as an ordinary array. This is how you handle the results of a database search, which is normally contained in a multidimensional array.

Image Tip  The shorthand syntax works only with PHP 5.4 or later, whereas array() works with all versions of PHP. Using array() has the marginal advantage of making the structure easier to visualize, but the array literal syntax borrowed from JavaScript involves less typing and is likely to be familiar to most web developers. Use whichever you feel comfortable with.

Using Print_r( ) to Inspect An Array

To inspect the contents of an array during testing, pass the array to print_r() like this (see inspect_array_01.php):

print_r($books);

Load inspect_array_01.php into a browser to see how print_r() outputs the contents of an ordinary array. The following screenshot shows how PHP displays a multidimensional array (the code is in inspect_array_02.php). Often, it helps to switch to Source view to inspect the details, as browsers ignore indenting in the underlying output. Alternatively, add HTML <pre> tags outside the PHP code block to preserve the indenting.

9781484206362_unFig03-05.jpg

Image Tip  Always use print_r() to inspect arrays; echo and print don’t work. To display the contents of an array in a webpage, use a foreach loop, as described later in this chapter.

The Truth According to PHP

Decision-making in PHP conditional statements is based on the mutually exclusive Boolean values of true and false. If the condition equates to true, the code within the conditional block is executed. If false, it’s ignored. Whether a condition is true or false is determined in one of these ways:

·     A variable set explicitly to one of the Boolean values

·     A value PHP interprets implicitly as true or false

·     The comparison of two non-Boolean values

Explicit Boolean Values

If a variable is assigned the value true or false and is used in a conditional statement, the decision is based on that value. The keywords true and false are case-insensitive and must not be enclosed in quotes; for example:

$OK = false;
if ($OK) {
    // do something
}

The code inside the conditional statement won’t be executed, because $OK is false.

Implicit Boolean (“Truthy” and “Falsy”) Values

Using implicit Boolean values provides a convenient shorthand, although it has the disadvantage—at least to beginners—of being less clear. Implicit Boolean values—or “truthy” and “falsy” values, as they’re sometimes called—rely on PHP’s relatively narrow definition of what it regards asfalse, namely:

·     The case-insensitive keywords false and null

·     Zero as an integer (0), a floating-point number (0.0), or a string ('0' or "0")

·     An empty string (single or double quotes with no space between them)

·     An empty array

·     SimpleXML objects created from empty tags

Everything else is true.

Image Tip  This explains why PHP interprets "false" (in quotes) as true. It’s a string, and all strings—except an empty one—are true.

Making Decisions by Comparing Two Values

Most true/false decisions are based on a comparison of two values using comparison operators. Table 3-5 lists the comparison operators used in PHP.

Table 3-5. PHP comparison operators used for decision-making

Table3-5

Image Caution  A single equal sign doesn’t perform comparisons; it assigns a value. When comparing two values, you must always use the equality operator (==), the identical operator (===), or their negative equivalents (!= and !==).

Testing More Than One Condition

Frequently, comparing two values is not enough. PHP allows you to set a series of conditions using logical operators to specify whether all or just some need to be fulfilled.

The most important logical operators in PHP are listed in Table 3-6. The logical Not operator applies to individual conditions rather than to a series.

Table 3-6. The main logical operators used for decision-making in PHP

Table3-6

Technically speaking, there is no limit to the number of conditions that can be tested. Each condition is considered in turn from left to right, and as soon as a defining point is reached, no further testing is carried out. When using &&, every condition must be fulfilled, so testing stops as soon as one turns out to be false. Similarly, when using ||, only one condition needs to be fulfilled, so testing stops as soon as one turns out to be true.

$a = 10;
$b = 25;
if ($a > 5 && $b > 20) // returns true
if ($a > 5 || $b > 30) // returns true, $b never tested

You should always design your tests to provide the speediest result. If all conditions must be met, evaluate the one most likely to fail first. If only one condition needs to be met, evaluate the one most likely to succeed first. If a set of conditions needs to be considered as a group, enclose them in parentheses, as follows:

if (($a > 5 && $a < 8) || ($b > 20 && $b < 40))

Image Note  PHP also uses AND in place of && and OR in place of ||. However, they aren’t exact equivalents. To avoid problems, it’s advisable to stick with && and ||.

Using the Switch Statement for Decision Chains

The switch statement offers an alternative to if . . . else for decision making. The basic structure looks like this:

switch(variable being tested) {
    case value1:
        statements to be executed
        break;
    case value2:
        statements to be executed
        break;
    default:
        statements to be executed
}

The case keyword indicates possible matching values for the variable passed to switch(). Each alternative value must be preceded by case and followed by a colon. When a match is made, every subsequent line of code is executed until the break or return keyword is encountered, at which point the switch statement comes to an end. A simple example follows:

switch($myVar) {
    case 1:
        echo '$myVar is 1';
        break;
    case 'apple':
    case 'orange':
        echo '$myVar is a fruit';
        break;
    default:
        echo '$myVar is neither 1 nor a fruit';
}

The main points to note about switch are as follows:

·     The expression following the case keyword is normally a number or a string. You can’t use a complex data type like an array or object.

·     To use comparison operators with case, you must repeat the variable being tested. So case > 100: won’t work, but case $myVar > 100: will.

·     Each block of statements should normally end with break or return unless you specifically want to continue executing code within the switch statement.

·     You can group several instances of the case keyword together to apply the same block of code to all of them.

·     If no match is made, any statements following the default keyword are executed. If no default has been set, the switch statement exits silently and continues with the next block of code.

Using the Ternary Operator

The ternary operator (?:) is a shorthand method of representing a conditional statement. Its name comes from the fact that it normally uses three operands. The basic syntax looks like this:

condition ? value if true : value if false;

Here is an example of it in use:

$age = 17;
$fareType = $age >= 16 ? 'adult' : 'child';

The second line tests the value of $age. If it’s greater than or equal to 16, $fareType is set to adult, otherwise $fareType is set to child. The equivalent code using if . . . else looks like this:

if ($age >= 16) {
    $fareType = 'adult';
} else {
    $fareType = 'child';
}

The if . . . else version is easier to read, but the conditional operator is more compact. Most beginners hate this shorthand, but once you get to know it, you’ll realize how convenient it can be.

You can leave out the value between the question mark and the colon. This has the effect of assigning the value of the condition to the variable if the condition is true. The preceding example could be rewritten like this:

$age = 17;
$adult = $age >= 16 ?: false; // $adult is true

In this case, the expression before the question mark is a comparison, so it can equate to only true or false. However, if the expression before the question mark is “truthy” (implicitly true), the value itself is returned. For example:

$age = 17;
$years = $age ?: 'unknown';  // $years is 17

Image Note  Omitting the value between the question mark and the colon is a specialized use of the ternary operator. It is mentioned here only to alert you to its meaning if you come across it elsewhere.

Creating Loops

loop is a section of code that is repeated until a certain condition is met. Loops are often controlled by setting a variable that counts the number of iterations. By increasing the variable by one each time, the loop comes to a halt when the variable gets to a preset number. Loops are also controlled by running through each item of an array. When there are no more items to process, the loop stops. Loops frequently contain conditional statements, so although they’re very simple in structure, they can be used to create code that processes data in often sophisticated ways.

Loops Using While and Do . . . While

The simplest type of loop is called a while loop. Its basic structure looks like this:

while (condition is true) {
    do something
}

The following code displays every number from 1 through 100 in a browser (you can test it in while.php in the files for this chapter). It begins by setting a variable ($i) to 1 and then uses the variable as a counter to control the loop, as well as displays the current number onscreen.

$i = 1;  // set counter
while ($i <= 100) {
    echo "$i<br>";
    $i++; // increase counter by 1
}

Image Tip  In the first half of this chapter, I warned against using variables with cryptic names. However, using $i as a counter is a widely accepted convention. If $i is already in use, the normal practice is to use $j or $k as counters.

A variation of the while loop uses the keyword do and follows this basic pattern:

do {
    code to be executed
} while (condition to be tested);

The difference between a do . . . while loop and a while loop is that the code within the do block is executed at least once, even if the condition is never true. The following code (in dowhile.php) displays the value of $i once, even though it’s greater than the maximum expected.

$i = 1000;
do {
    echo "$i<br>";
    $i++; // increase counter by 1
} while ($i <= 100);

The danger with while and do . . . while loops is forgetting to set a condition that brings the loop to an end or setting an impossible condition. This is known as an infinite loop that either freezes your computer or causes the browser to crash.

The Versatile for Loop

The for loop is less prone to generating an infinite loop because you are required to declare all the conditions of the loop in the first line. The for loop uses the following basic pattern:

for (initialize loop; condition; code to run after each iteration) {
    code to be executed
}

The following code does exactly the same as the previous while loop, displaying every number from 1 to 100 (see forloop.php):

for ($i = 1; $i <= 100; $i++) {
    echo "$i<br>";
}

The three expressions inside the parentheses control the action of the loop (note that they are separated by semicolons, not commas):

·     The first expression is executed before the loop starts. In this case, it sets the initial value of the counter variable $i to 1.

·     The second expression sets the condition that determines how long the loop should continue to run. This can be a fixed number, a variable, or an expression that calculates a value.

·     The third expression is executed at the end of each iteration of the loop. In this case, it increases $i by 1, but there is nothing stopping you from using bigger increments. For instance, replacing $i++ with $i+=10 in this example would display 1, 11, 21, 31, and so on.

Looping Through Arrays and Objects with Foreach

The final type of loop in PHP is used with arrays and objects. It takes two forms, both of which use temporary variables to handle each element. If you only need to do something with the element’s value, the foreach loop takes the following form:

foreach (variable_name as element) {
    do something with element
}

The following example loops through the $shoppingList array and displays the name of each item (the code is in foreach_01.php):

$shoppingList = ['wine', 'fish', 'bread', 'grapes', 'cheese'];
foreach ($shoppingList as $item) {
    echo $item.'<br>';
}

Image Caution  The foreach keyword is one word. Inserting a space between for and each doesn’t work.

Although the preceding example uses an indexed array, you can also use the simple form of the foreach loop with an associative array.

The alternative form of the foreach loop gives access to both the key and the value of each element. It takes this slightly different form:

foreach (variable_name as key => value) {
    do something with key and value
}

This next example uses the $book associative array from the “Creating arrays” section earlier in this chapter and incorporates the key and value of each element into a simple string, as shown in the following screenshot (see foreach_02.php):

foreach ($book as $key => $value) {
    echo "$key: $value<br>";
}

9781484206362_unFig03-06.jpg

Image Note  Apart from arrays, the main use of a foreach loop is with a special type of object known as an iterator. You’ll see how to use iterators in Chapter 7.

Breaking Out Of a Loop

To bring a loop prematurely to an end when a certain condition is met, insert the break keyword inside a conditional statement. As soon as the script encounters break, it will exit the loop.

To skip the code in a loop when a certain condition is met, use the continue keyword. Instead of exiting, it returns to the top of the loop and deals with the next element. For example, the following loop skips the current element if $photo has no value:

foreach ($photos as $photo) {
    if (empty($photo)) continue;
    // code to display a photo
}

Modularizing Code with Functions

Functions offer a convenient way of running frequently performed operations. In addition to the large number of built-in functions, PHP lets you create your own. The advantages are that you write the code only once, rather than needing to retype it everywhere you need it. This not only speeds up development but also makes your code easier to read and maintain. If there’s a problem with the code in your function, you can update it in just one place rather than hunting through your entire site. Moreover, functions usually speed up the processing of your pages.

Building your own functions in PHP is easy. You simply wrap a block of code in a pair of curly braces and use the function keyword to name the new function. The function name is always followed by a pair of parentheses. The following—admittedly trivial—example demonstrates the basic structure of a custom-built function (see functions_01.php in the files for this chapter):

function sayHi() {
    echo 'Hi!';
}

Simply putting sayHi(); in a PHP code block results in Hi! being displayed onscreen. This type of function is like a drone: it always performs exactly the same operation. For functions to be responsive to circumstances, you need to pass values to them as arguments.

Passing Values to Functions

Let’s say you want to adapt the sayHi() function so that it displays someone’s name. You do this by inserting a variable between the parentheses in the function declaration. The same variable is then used inside the function to display whatever value is passed to the function. To pass more than one argument to a function, separate the variables with commas inside the opening parentheses. This is what the revised function looks like (see functions_02.php):

function sayHi($name) {
    echo "Hi, $name!";
}

You can now use this function inside a page to display the value of any variable passed to sayHi(). For instance, if you have an online form that saves someone’s name in a variable called $visitor, and Ben visits your site, you can give him the sort of personal greeting shown in the following screenshot by putting sayHi($visitor); in your page.

9781484206362_unFig03-07.jpg

A downside of PHP’s weak typing is that if Ben is being particularly uncooperative, he might type 5 into the form instead of his name, giving you not quite the type of high five you might have been expecting.

9781484206362_unFig03-08.jpg

This is why you should check user input before using it in any critical situation.

Variable Scope—Functions as Black Boxes

It’s also important to understand that functions create a separate environment that is rather like a black box. Normally what goes on inside the function has no impact on the rest of the script, unless it returns a value, as described in the next section. Variables inside a function remain exclusive to the function. This example should illustrate the point (see functions_04.php):

function doubleIt($number) {
    $number *= 2;
    echo '$number is ' . $number . '<br>';
}
$number = 4;
doubleIt($number);
echo '$number is ' . $number;

The first four lines define a function called doubleIt(), which takes a number, doubles it, and displays it onscreen. The rest of the script assigns the value 4 to $number. Then it passes $number as an argument to doubleit(). The function processes $number and displays 8. After the function comes to an end, $number is displayed onscreen by echo. This time, it’s 4 and not 8, as shown in the following screenshot:

9781484206362_unFig03-09.jpg

This demonstrates that $number in the main script is totally unrelated to the variable with the same name inside the function. This is known as the scope of the variable. Even if the value of the variable changes inside a function, variables with the same name outside are not affected. To avoid confusion, it’s a good idea to use variable names in the rest of your script that are different from those used inside functions. This isn’t always possible, so it’s useful to know that functions work like little black boxes and don’t normally have any direct impact on the values of variables in the rest of the script.

Another aspect of variable scope is that a function cannot normally access values in the outer script unless they’re passed to the function as arguments.

Image Note  PHP superglobal variables, such as $_POST and $_GET, are not affected by variable scope. They’re always available, which is why they’re called superglobal.

Returning Values from Functions

There’s more than one way to get a function to change the value of a variable passed to it as an argument, but the most important method is to use the return keyword and to assign the result either to the same variable or to another one. This can be demonstrated by amending thedoubleIt() function like this (the code is in functions_05.php):

function doubleIt($number) {
    return $number *= 2;
}
$num = 4;
$doubled = doubleIt($num);
echo '$num is: ' . $num . '<br>';
echo '$doubled is: ' . $doubled;

9781484206362_unFig03-10.jpg

This time, I have used different names for the variables to avoid confusing them. I have also assigned the result of doubleIt($num) to a new variable. The benefit of doing this is that both the original value and the result of the calculation are now available. You won’t always want to keep the original value, but it can be very useful at times.

Passing by Reference—Changing the Value of an Argument

Although functions don’t normally change the value of variables passed to them as arguments, there are occasions when you do want to change the original value rather than capture a return value. To do so, when defining the function, you prefix the parameter you want to change with an ampersand, like this:

function doubleIt(&$number) {
    $number *= 2;
}

Notice that this version of the doubleIt() function doesn’t echo the value of $number, nor does it return the value of the calculation. Because the parameter between the parentheses is prefixed by an ampersand, the original value of a variable passed as an argument to the function will be changed. This is known as passing by reference.

The following code (found in functions_06.php) demonstrates the effect:

$num = 4;
echo '$num is: ' . $num . '<br>';
doubleIt($num);
echo '$num is now: ' . $num;

9781484206362_unFig03-11.jpg

The ampersand is used only in the function definition, not when the function is invoked.

Image Note  Generally speaking, it’s not a good idea to use functions to change the original values of variables passed to them as arguments because there can be unexpected consequences if the variable is used elsewhere in a script. However, there are situations in which it makes a lot of sense to do this. For example, the built-in array-sorting functions use pass by reference to affect the original array.

Where to Locate Custom-Built Functions

If your custom-built function is found on the same page it’s being used, it doesn’t matter where you declare the function; it can be either before or after it’s used. It’s a good idea, however, to store functions together, either at the top or the bottom of a page. This makes them easier to find and maintain.

Functions that are used in more than one page are best stored in an external file that is included in each page. Including external files with include and require is covered in detail in the next chapter. When functions are stored in external files, you must include the external file beforecalling any of its functions.

Creating New Variables Dynamically

PHP supports the creation of what’s known as a variable variable. Although that looks like a typographical error, it’s not. Simply put, a variable variable creates a new variable that derives its name from an existing variable. This concept can be difficult to understand, but the following examples should clarify the situation (the code is in variable_variables.php).

The following statement assigns the string “city” to a variable called $location:

$location = 'city';

You create a variable variable by using two dollar signs, like this:

$$location = 'London';

The variable variable takes the value of the original variable as its name. In other words, $$location is the same as $city.

echo $city; // London

Although this demonstrates how variable variables work, it’s not a very practical example. So let’s consider a situation that creates new variables dynamically. Let’s say you have an associative array like this:

$fields = [
    'name'     => 'David',
    'email'    => 'david@example.com',
    'comments' => "What's a variable variable?"
];

To get the value of an array element, you would use the name of its key as a string in square brackets after the array variable, like this:

echo $fields['name'];  // David

Instead of using this syntax, you could use a foreach loop to generate $name, $email, and $comments variables dynamically as variable variables, as follows:

foreach ($fields as $key => $value) {
    $$key = $value;
}
echo $name . '<br>';
echo $email . '<br>';
echo $comments;

This produces the following output:

9781484206362_unFig03-12.jpg

Inside the loop, $$key is a variable variable that creates a new variable based on the value of $key. The loop also assigns $value to $$key. The first time the loop runs, $key is “name” and $value is “David.” Thus it creates a variable called $name with the value “David.” As the loop continues to run, $$key creates new variables called $email and $comments.

You’ll see this technique used in the mail-processing script in Chapter 5.

Image Tip  To indicate that the double $ is intentional, I like to enclose the variable being used to create the variable variable in curly braces like this: ${$key}. The braces are purely optional, but make the code easier to read.

PHP Quick Checklist

This chapter contains a lot of information that is impossible to absorb in one sitting, but hopefully the first half has given you a broad overview of how PHP works. The second half fills in a lot of essential details that you can refer to as you progress through this book. Here’s a reminder of some of the main points:

·     Always give PHP pages the correct filename extension, normally .php.

·     Enclose all PHP code between the correct tags: <?php and ?>.

·     Avoid the short form of the opening tag: <?. Using <?php is more reliable.

·     It’s recommended to omit the closing PHP tag in files that contain only PHP code.

·     PHP variables begin with $ followed by a letter or the underscore character.

·     Choose meaningful variable names and remember they’re case-sensitive.

·     Use comments to remind you what your script does.

·     Remember that numbers don’t require quotes, but strings (text) do.

·     You can use either single or double quotes, but the outer pair must match.

·     Use a backslash to escape quotes of the same type inside a string.

·     To store related items together, use an array.

·     Use conditional statements, such as if and if . . . else, for decision making.

·     Simplify repetitive tasks with loops.

·     Use functions to perform preset tasks.

·     Display PHP output with echo or print.

·     Inspect the content of arrays with print_r().

·     With most error messages, work backward from the position indicated.

·     Keep smiling—and remember that PHP is not difficult.