LIGHTENING YOUR WORKLOAD WITH INCLUDES
91
Figure 4-12. The ugly gap is removed by creating a style rule directly related to the image size.
If the caption still protrudes, make sure theres no gap between the closing PHP tag and
px
in the
<style>
block. CSS does not permit whitespace between the value and unit of measurement.
8. The code in random_image.php and the code you have just inserted prevent errors if the
selected image cant be found, but the code that displays the image is devoid of similar
checks. Temporarily change the name of one of the images, either in random_image.php or in
the images folder. Reload index.php several times. Eventually, you should see an error
message like that in Figure 4-13. It looks very unprofessional.
Figure 4-13. An error in an include file can destroy the look of your page.
9. The conditional statement at the foot of random_image.php sets $imageSize only if the
selected image both exists and is readable, so if $imageSize has been set, you know its all
systems go. Add the opening and closing blocks of a conditional statement around the <div>
that displays the image in index.php like this:
<?php if (isset($imageSize)) { ?>
<div id="pictureWrapper">
CHAPTER 4
92
<img src="<?php echo $selectedImage; ?>" alt="Random image"
class="picBorder" <?php echo $imageSize[3]; ?> />
<p id="caption"><?php echo $caption; ?></p>
</div>
<?php } ?>
Images that exist will display normally, but youll avoid any embarrassing error messages in
case of a missing or corrupt filea much more professional look. Dont forget to restore the
name of the image you changed in the previous step. You can check your code against
index_05.php and random_image_02.php in the ch04 folder.
Preventing errors with include files
Many hosting companies turn off error reporting for notices, so you probably wouldnt be aware of the
problem shown in Figure 4-13 if you did all your testing on your remote server. However, its important to
eliminate all errors before deploying PHP pages on the Internet. Just because you cant see the error
message, doesnt mean your page is OK.
Pages that use a server-side technology such as PHP deal with a lot of unknowns, so its wise to code
defensively, checking values before using them. This section describes measures you can take to
prevent and troubleshoot errors with include files.
Checking the existence of variables
The lesson that can be drawn from PHP Solution 4-7 is that you should always use isset() to verify the
existence of a variable that comes from an include file and wrap any code that uses it in a conditional
statement. In this particular case, you know theres no image to display if $imageSize doesnt exist, so
the pictureWrapper <div> is dropped. However, in other cases, you might be able to assign a default
value to the variable like this:
if (!isset($someVariable)) {
$someVariable =
default value
;
}
This uses the logical Not operator (see Table 3-6 in Chapter 3) to check if $someVariable has not been
set. If $someVariable doesnt exist, its assigned a default value, which can then be used later in your
script. If it does exist, the code inside the conditional statement is skipped, and the original value is used.
Checking whether a function or class has been defined
Include files are frequently used to define custom functions or classes. Attempting to use a function or
class that hasnt been defined triggers a fatal error. To check whether a function has been defined, pass
the name of the function as a string to function_exists(). When passing the name of the function to
function_exists(), omit the parentheses at the end of function name. For example, you check whether
a function called doubleIt() has been defined like this:
if (function_exists('doubleIt')) {
// use doubleIt()
}
Download from Wow! eBook <www.wowebook.com>
LIGHTENING YOUR WORKLOAD WITH INCLUDES
93
To check whether a class has been defined, use class_exists() in the same way, passing a string
containing the class name as the argument:
if (class_exists('MyClass')) {
// use MyClass
}
Assuming you want to use the function or class, a more practical approach is to use a conditional
statement to include the definition file if the function or class hasnt already been defined. For example, if
the definition for doubleIt() is in a file called utilities.inc.php:
if (!function_exists('doubleIt')) {
require_once('includes/utilities.inc.php');
}
Temporarily turning on error messages
Error messages are there to help the developer. Unfortunately, displaying them in a live website exposes
information that could be useful to an attacker, which is why its now common for hosting companies to
turn off the display of error messages. Depending on the nature of the error, all you might see when
accessing the page is a blank screen. This isnt very helpful when you need to find out whats wrong with a
page that worked perfectly in your local testing environment.
Fortunately, its easy to turn on the display of error messages temporarily for an individual page with
ini_set(), which can be used to override some directives in php.ini, the servers PHP configuration
file. Add the following code at the top of the page thats causing problems:
<?php ini_set('display_errors', '1'); ?>
Upload the file to your remote server, and reload the page in your browser. You should then be able to read
the error message onscreen. Fix the problem, and test the page again. If the page displays correctly,
remove the extra line of code.
If you still see a blank screen, it means theres a syntax error in your PHP code. Using
ini_set()
has no effect if theres a parse error.
The most common cause of errors is forgetting to upload the include file to your remote server. Even if you
have uploaded all the files, you might get an error message telling you that you dont have permission to
access an include file. This is likely to happen in the following circumstances:
The server is running in safe mod e : If your hosting company is running PHP in a highly
restricted way, you will see a warning that a safe mode restriction is in effect. Run phpinfo(),
and check the value of safe_mode_include_dir in the Core section. All your include files
must be stored in this location. Adjust your site structure accordingly. Safe mode is scheduled
to be removed from the next major version of PHP, so this problem is less common.
CHAPTER 4
94
The open_basedir directive has been set: The open_basedir directive restricts your
ability to include or open files. This should affect you only when the include file is outside your
web servers document root. The warning message produced by PHP lists the allowed path(s).
Move your include file to a permitted location, and adjust the path in the include command
accordingly.
Dealing with missing include files
Assuming your include files are working normally on your remote server, thats probably all the error
checking you need. However, if your remote server displays error messages, you should take steps to
suppress them in case an include file is accidentally deleted or corrupted.
A rather crude, but effective way is to use the PHP error control operator (@), which suppresses error
messages associated with the line of code in which its used. You place the error control operator either at
the beginning of the line or directly in front of the function or command that you think might generate an
error like this:
@ include('./includes/random_image.php');
The problem with the error control operator is that it hides errors, rather than working around them. Its only
one character, so its easy to forget you have used it. Consequently, you can waste a lot of time looking
for errors in the wrong part of your script. If you use the error control operator, the @ mark should be the
first thing you remove when troubleshooting a problem.
The other drawback is that you need to use the error control operator in every line that might generate an
error message, because it affects only the current line.
A better way of suppressing error messages in a live website is to turn off the display_errors directive
in the web servers configuration. The most effective way is to edit php.ini if your hosting company gives
you control over its settings. Alternatively, if your server runs on Apache and you have permission to
change the configuration with an .htaccess file, you should add the following command to the .htaccess
file in your server root folder:
php_flag display_errors Off
If neither option is available, add the following line at the top of any script that uses include files:
<?php ini_set('display_errors', '0'); ?>
All the techniques suggested so far only suppress error messages if an include file cant be found. If a
page would be meaningless without the include file, you should redirect the user to an error page if the
include file is missing.
One way to do so is to throw an exception like this:
$file = 'includes/menu.inc.php';
if (file_exists($file) && is_readable($file)) {
include($file);
} else {
throw new Exception("$file can't be found");
}
LIGHTENING YOUR WORKLOAD WITH INCLUDES
95
When using code that might throw an exception, you need to wrap it in a try block and create a catch
block to handle the exception (see “Handling Exceptions” in Chapter 3). The next PHP solution shows how
to do this.
PHP Solution 4-8: Redirecting when an include file cant be found
This PHP solution shows how to redirect users to a different page if an include file cant be found. If you
have designed and tested your site thoroughly, this technique should not be necessary on most pages
that use include files. However, this is by no means a pointless exercise. It demonstrates several
important features of PHP: how to throw and catch exceptions and how to redirect to another page. As
youll see from the following instructions, redirection isnt always straightforward. This PHP solution shows
how to overcome the most common problem.
Continue working with index.php from PHP Solution 4-7. Alternatively, use index_05.php from the ch04
folder.
1. Copy error.php from the ch04 folder to the site root. Dont update the links in the page if your
editing program prompts you to do so. This is a static page that contains a generic error
message and links back to the other pages.
2. Open index.php in your editing program. The navigation menu is the most indispensible
include file, so edit the include command in index.php like this:
$file = 'includes/menu.inc.php';
if (file_exists($file) && is_readable($file)) {
include($file);
} else {
throw new Exception("$file can't be found");
}
Storing the path of the include file in a variable like this avoids the need to retype it four times,
reducing the likelihood of spelling mistakes.
3. To redirect the user to another page, you use the header() function. However, redirection
doesnt work if any output has been sent to the browser before you call header(). Unless
theres a syntax error, the PHP engine normally processes a page from the top outputting the
HTML until it reaches a problem. This means that output will have already begun by the time the
PHP engine gets to this code. To prevent this from happening, start the try block before any
output is generated. (This actually wont work, but bear with me, because it demonstrates an
important point.)
Scroll to the top of the page, and edit the opening PHP code block like this:
<?php try {
include('./includes/title.inc.php');
include('./includes/random_image.php'); ?>
This opens the try block.