85
61
Opening a File
In a Unix environment,you use forward slashes (
/
) in directory paths.If you are using
a Windows platform,you can use forward (
/
) or backslashes (
\
).If you use backslashes,
they must be escaped (marked as a special character) for
fopen()
to understand them
properly.To escape a character,you simply add an additional backslash in front of it,as
shown in thefollowing:
$fp = fopen(“$DOCUMENT_ROOT\\..\\orders\\orders.txt”, ‘w’);
Very few people use backslashes in paths within PHP because it means the code will
work only in Windows environments.If you use forward slashes,you can often move
your code between Windows and Unix machines without alteration.
The second
fopen()
parameter is the file mode,which should be a string.This string
specifies what you want to do with the file.In this case,we are passing
‘w’
to
fopen()
;
this means “open the file for writing.”A summary of file modes is shown in Table 2.1.
Table 2.1 1 Summary of File Modes for fopen()
Mode Mode Name
Meaning
r
Read
Open the file for reading,beginning from the start of the file.
r+
Read
Open the file for reading and writing,beginning from the start of
the file.
w
Write
Open the file for writing,beginning from the start of the file.If the
file already exists,delete the existing contents.If it does not exist,try
to create it.
w+
Write
Open the file for writing and reading,beginning from the start of
the file.If the file already exists,delete the existing contents.If it
does not exist,try to create it.
x
Cautious write e Open the file for writing,beginning from the start of the file.If the
file already exists,it will not be opened,
fopen()
will return
false
,and PHP will generate a warning.
x+
Cautious write e Open the file for writing and reading,beginning from the start of
the file.If the file already exists,it will not be opened,
fopen()
will
return
false
,and PHP will generate a warning.
a
Append
Open the file for appending (writing) only,starting from the end of
the existing contents,if any.If it does not exist,try to create it.
a+
Append
Open the file for appending (writing) and reading,starting from the
end of the existing contents,if any.If it does not exist,try to create it.
b
Binary
Used in conjunction with one of the other modes.You might want
to use this mode if your file system differentiates between binary and
text files.Windows systems differentiate;Unix systems do not.The
PHP developers recommend you always use this option for maxi-
mum portability.It is the default mode.
t
Text
Used in conjunction with one of the other modes.This mode is an
option only in Windows systems.It is not recommended except
before you have ported your code to work with the
b
option.
68
62
Chapter 2 2 Storing and Retrieving Data
The file mode you use in the example depends on how the system will be used.We used
‘w’
,which allows only one order to be stored in the file.Each time a new order is
taken,it overwrites the previous order.This usage is probably not very sensible,so you
would better off specifying append mode (and binary mode,as recommended):
$fp = fopen(“$DOCUMENT_ROOT/../orders/orders.txt”, ‘ab’);
The third parameter of
fopen()
is optional.You can use it if you want to search the
include_path
(set in your PHP configuration;see Appendix A,“Installing PHP5 and
MySQL5”) for a file.If you want to do this,set this parameter to
1
.If you tell PHP to
search the
include_path
,you do not need to provide a directory name or path:
$fp = fopen(‘orders.txt’, ‘ab’, true);
The fourth parameter is also optional.The
fopen()
function allows filenames to be pre-
fixed with a protocol (such as
http://
) and opened at a remote location.Some proto-
cols allow for an extra parameter.We look at this use of the
fopen()
function in the
next section of this chapter.
If
fopen()
opens the file successfully,a resource that is effectively a pointer to the file
is returned and should be stored in a variable—in this case,
$fp
.You use this variable to
access the file when you actually want to read from or write to it.
Opening Files Through FTP or HTTP
In additionto opening local files for reading and writing,you can open files via FTP,
HTTP,and other protocols using
fopen()
.You can disable this capability by turning off
the
allow_url_fopen
directive in the
php.ini
file.If you have trouble opening remote
files with
fopen()
,check your
php.ini
file.
If the filename you use begins with
ftp://
,a passive mode FTP connection will be
opened to the server you specify and a pointer to the start of the file will be returned.
If the filename you use begins with
http://
,an HTTP connection will be opened to
the server you specify and a pointer to the response will be returned.When using HTTP
mode with older versions of PHP,you must specify trailing slashes on directory names,as
shown in the following:
http://www.example.com/
not
http://www.example.com
When you specify the latter form of address (without the slash),a web server normal-
ly uses an HTTP redirect to send you to the first address (with the slash).Try it in your
browser.
22
63
Opening a File
Prior to PHP 4.0.5,the
fopen()
function did not support HTTP redirects,so you
had to specify URLs that referred to directories with a trailing slash.
As of PHP 4.3.0,you can now open files over SSL as long as you have compiled or
enabled support for OpenSSL and you begin the name of the file with
https://
.
Remember that the domain names in your URL are not case sensitive,but the path
and filename mightbe.
Addressing Problems Opening Files
An error you might make is trying to open a file you don’t have permission to read from
or write to.(This error occurs commonly on Unix-like operating systems,but you may
also see it occasionally under Windows.) When you do,PHP gives you a warning similar
to the one shown in Figure 2.2.
Figure 2.2 2 PHP specifically warns you when a file can’t be opened.
If you receive this error,you need to make sure that the user under which the script
runs has permission to access the file you are trying to use.Depending on how your
server is set up,the script might be running as the web server user or as the owner of
the directory where the script is located.
58
64
Chapter 2 2 Storing and Retrieving Data
On most systems,the script runs as the web server user.If your script is on a Unix
system in the
~/public_html/chapter2/
directory,for example,you could create a
world-writeable directory in which to store the order by typing the following:
mkdir ~/orders
chmod 777 ~/orders
Bear in mind that directories and files that anybody can write to are dangerous.In par-
ticular,directories that are accessible directly from the Web should not be writeable.For
this reason,our
orders
directory is two subdirectories back,above the
public_html
directory.We discuss security more in Chapter 15,“E-commerce Security Issues.”
Incorrect permission setting is probably the most common thing that can go wrong
when opening a file,but it’s not the only thing.If you can’t open the file,you really need
to know this so that you don’t try to read data from or write data to it.
If the call to
fopen()
fails,the function will return
false
.You can deal with the
error in a more user-friendly way by suppressing PHP’s error message and giving your
own:
@ $fp = fopen(“$DOCUMENT_ROOT/../orders/orders.txt”, ‘ab’);
if (!$fp)
{
echo ‘<p><strong> Your order could not be processed at this time. ‘
.’Please try again later.</strong></p></body></html>’;
exit;
}
The
@
symbol in front of the call to
fopen()
tells PHP to suppress any errors resulting
from the function call.Usually,it’s a good idea to know when things go wrong,but in
this case we’re going to deal with that problem elsewhere.
You can also write this line as follows:
$fp = @fopen(“$DOCUMENT_ROOT/../orders/orders.txt”, ‘a’);
Using this method tends to make it less obvious that you are using the error suppression
operator,so it may make your code harder to debug.
The method described here is a simplistic way of dealing with errors.We look at a
more elegant method for error handling in Chapter 7,“Exception Handling.”But one
thing at a time.
The
if
statement tests the variable
$fp
to see whether a valid file pointer was
returned from the
fopen
call;if not,it prints an error message and ends script execution.
Because the page finishes here,notice that we have closed the HTML tags to give rea-
sonably valid HTML.
The output when using this approach is shown in Figure 2.3.
54
65
Writing to a File
Figure 2.3 3 Using your own error messages instead of PHP’s can be more
user friendly.
Writing to a File
Writingto a file in PHP is relatively simple.You can use either of the functions
fwrite()
(file write) or
fputs()
(file put string);
fputs()
is an alias to
fwrite()
.You
call
fwrite()
in the following way:
fwrite($fp, $outputstring);
This function call tells PHP to write the string stored in
$outputstring
to the file
pointed to by
$fp
.
One new alternative to
fwrite()
is the
file_put_contents()
function.It has the
following prototype:
int file_put_contents ( string filename,
string data
[, int flags
[, resource context]])
This function writes the string contained in
data
to the file named in
filename
with-
out any need for an
fopen()
(or
fclose()
) function call.This function is new in
PHP5,and is a matched pair for
file_get_contents()
,which we discuss shortly.You
most commonly use the
flags
and
context
optional parameters when writing to
remote files using,for example,HTTP or FTP.(We discuss these function in Chapter 19,
“Using Network andProtocol Functions.”)
62
66
Chapter 2 2 Storing and Retrieving Data
Parameters for fwrite()
Thefunction
fwrite()
actually takes three parameters,but the third one is optional.The
prototype for
fwrite()
is
int fwrite ( resource handle, string string g [, int length])
The third parameter,
length
,is the maximum number of bytes to write.If this parame-
ter is supplied,
fwrite()
will write
string
to the file pointed to by
handle
until it
reaches the end of
string
or has written
length
bytes,whichever comes first.
You can obtain the string length by using PHP’s built-in
strlen()
function,as follows:
fwrite($fp, $outputstring, strlen($outputstring));
You may want to use this third parameter when writing in binary mode because it helps
avoid some cross-platform compatibility issues.
File Formats
Whenyou are creating a data file like the one in the example,the format in which you
store the data is completely up to you.(However,if you are planning to use the data file
in another application,you may have to follow that application’s rules.)
Now construct a string that represents one record in the data file.You can do this as
follows:
$outputstring = $date.”\t”.$tireqty.” tires \t”.$oilqty.” ” oil\t”
.$sparkqty.” spark plugs\t\$”.$totalamount
.”\t”. $address.”\n”;
In this simple example,you store each order record on a separate line in the file.Writing
one record per line gives you a simple record separator in the newline character.Because
newlines are invisible,you can represent them with the controlsequence
“\n”
.
Throughout the book,we write the data fields in the same order every time and sep-
arate fields with a tab character.Again,because a tab character is invisible,it is represent-
ed by the control sequence
“\t”
.You may choose any sensible delimiter that is easy to
read back.
The separator or delimiter character should be something that will certainly not
occur in the input,or you should process the input to remove or escape out any
instances of the delimiter.We look at processing the input in Chapter 4,“String
Manipulation and Regular Expressions.”For now,you can assume that nobody will place
a tab into the order form.It is difficult,but not impossible,for a user to put a tab or
newline into a single-line HTML input field.
Using a special field separator allows you to split the data back into separate variables
more easily when you read the data back.We cover this topic in Chapter 3,“Using
Arrays,”and Chapter 4.Here,we treat each order as a single string.
After a few orders are processed,the contents of the file look something like the
example shown in Listing 2.1.
Documents you may be interested
Documents you may be interested