Sunday, September 30, 2007

File Creation and Editing with Filesystem Functions

Intended Audience

This tutorial is intended for PHP programmers that wish to use the Filesystem Functions of PHP to create files on their webserver via PHP.

A basic understanding of PHP and file systems in general is assumed.

For the one of the examples a fictional MySQL database is referenced; for this example, knowledge of MySQL is assumed.

Overview

Most web programming is limited to creating server side scripts that are displayed in a browser. However, sometimes you need to go beyond that and create files on the server itself. What you need may be a simple hit counter, or something as complicated as creating a complete Excel spreadsheet file on-the-fly from a database.

In PHP this is all made possible by the built in Filesystem Functions. This tutorial will explain how to use some of these very useful functions.

Background Information

PHP has many Filesystem Functions, only a few are mentioned in this tutorial. You can read about all of the Filesystem Functions in the PHP Manual: http://www.php.net/manual/en/ref.filesystem.php

Functions Used

fopen();
fwrite();
fputs();
fgets();
fclose();
readfile();

Learning Objectives

In this tutorial you will learn how to read, write, and edit files via PHP’s Filesystem Functions. You will also learn the proper permissions needed to create and edit files on a system.

You will also learn how to create a simple hit counter, as well as a CSV file compatible with Excel.

Permissions

It is important to remember a few key things when working with PHP and file creation. PHP runs via your webserver and therefore has the same rights as your webserver. Since most webservers do not run with super-user status (root in Unix/Linux, or administrator in Windows) you will need to make sure the folders and files you want to edit allow the webserver write access.

Got that all set? If you already know what you are doing with permissions, you can skip to the next section.

If you are running Unix or Linux with Apache you will need to change the owner of your files to ‘nobody’ or ‘www’ depending on your install. If you don’t know what user simply type:

ps -aux | grep httpd

This will show you the apache processes running on your server, look to see the name of the user running the process. Now you need to change the permissions of your files.

File: chown www file.txt
Directory: chown www folder1/

This will change the owner of the file file.txt (or the directory folder1/) to www, thus allowing PHP via Apache to edit the file.

PHP Configuration File

PHP will allow you to open files via a URL as well as a system path. This behavior is controlled by the php.ini file, you can turn this functionality on and off, as well as set the password used for anonymous ftp connections. If you intend on using fopen() with URLs then make sure your php.ini settings resemble the example below.

;;;;;;;;;;;;;;;;;;
;
Fopen wrappers ;
;;;;;;;;;;;;;;;;;;

;
Whether to allow the treatment of URLs (like http:// or ftp://) as files.
allow_url_fopen = On

; Define the anonymous ftp password (your email address)
from="john@doe.com"

Recently there has been some concern as to the possible security problems associated with enabling this option, therefore if you have no need to open files via URLs it is strongly recommended that you set allow_url_fopen = Off.

How It Works

File creation is a snap with PHP, but to make things easier we are going to make a directory that has permissions that allow the webserver to write. Create a directory called test/ and make sure the permissions on it are set as explained above.

Create a File

Now that you have the right permissions you can go ahead and make your first file. Create a PHP script named file.php inside the test/ folder and include the following code:

php

$file
= "./test.txt";
$fp = fopen ("$file", "wb");

$content = "Hello, I am a File!";
fwrite($fp, $content);
fclose($fp);

echo "Wrote to ($file):

";
readfile($file);
echo "
";

?>

So what does all that do?

First off we have $file which just sets the name of the file you are creating with the script, in this case file.txt.

Next we have $fp or “file pointer” this is used with the fopen() function to first look for a file (specified by $file) and if not found create it. fopen() will be described in more detail in the next section.

The contents of the file will be determined in this case by the variable $content, and will be written to the file by the function fwrite(). You should now close your file, as you do not need to write anymore data to it via fclose(). For this example, we will print out what has been written to the file:

readfile($file) .

If the script has run correctly, you will see something like this:

Wrote to (./test.txt):
Hello, I am a File!

More on fopen();

Now let’s look a little more closely at what is going on here.

fopen() is the command that opens the file for reading or writing. It accepts a filename and one of six arguments: r, r+, w, w+, a, a+ as well as b for binary safe writing of files (Windows needs this for non-text files, for Unix it doesn’t matter. The safest way is thus to always use the “b” when working with binary, non-text files.)

In our case we used wb to open a binary file for writing only. This will truncate the file length to zero so that the file is blank and then place the content at the beginning of the file. If the file does not exist, it will attempt to create it.

Here is a breakdown of the modes:

w: This is the write mode, used to open a file for writing, Whenever this is used the file associated with the command will be recreated. w+ enables read/write mode.
r: This mode is used to open a file for reading. r+ enables read/write mode.
a: This is the append mode, your content will be added to the file therefore keeping any data already in the file. Change to a+ to enable read/write mode.

Create a PHP Hit Counter

Now that you have created a simple file; let’s get to something a little more useful. Create a file called counter.php and input the following code. Again, make sure this file in a directory that has write privileges for the webserver.

php
if(file_exists("count.dat")) {

// open for reading
$fp = fopen("count.dat", "r");
$count
= fgets($fp, 1024);
$count++;
fclose($fp);
echo "$count people have visited this page.";
// open for writing
$fp = fopen("count.dat", "w");
fwrite($fp, $count);
fclose($fp);

} else {

// create a new file
$fp = fopen("count.dat", "w"); // open for writing
fwrite($fp, "1");
echo "one person has visited this page.";
fclose($fp);

}
?>

This script will create a file called count.dat and put the integer 1 in it. If file_exists()is true, it will add one more to that number each time the script is invoked.

As you can see, we have used fopen()to first open the file for reading to get the number of hits, then again for writing to add a hit to the counter.

Unfortunately fopen()does not properly lock files, this can cause problems with this kind of script as it could allow multiple Apache processes to edit the same count.dat file. Because Apache does not realize the file is open, it may corrupt the file if it tried to write to two files at the same time. However, since this script is extremely short, and requires very little runtime problems are unlikely.

Excel Compatible CSV Files

An another great use for this is the creation of CSV, or “Comma Separated Values”. These files are compatible with Microsoft Excel and many other spreadsheet programs on multiple platforms. CSV files work by simply putting commas in between data elements and separating new rows by new lines.

For example, say you have a database with your users’ names, e-mail addresses and phone numbers. You want your Marketing department to have an Excel spread sheet with this information. Here is what your database structure might look like:


Name
E-Mail
Phone
Lee Johnson
lee@lyfe.com
714-555-2345
Steven Mullins
smullins@yahoo.com
703-555-7516
William Polick
yetti@aol.com
313-555-8836

This structure converts to CSV like this:

Name,E-Mail,Phone
Lee Johnson,lee@lyfe.com,714-555-2345
Steven Mullins,smullins@yahoo.com,703-555-7516
William Polick,yetti@aol.com,313-555-88836

Knowing this, all you need to do is create an array with values from your database, then put those values into the CSV format. This will allow you to have a dynamically generated CSV file of the data.

Here is an example:

php

mysql_connect
("localhost", "root");
mysql_select_db("users");

$fp = fopen ("./data.csv", "wb");

// MySQL Queries
$query = "SELECT * FROM Users order by Name";
$result = mysql_query($query);

// Coloums
$columns = "Name,E-Mail,Phone\n";
fwrite ($fp, $colums);

// MySQL Array
if ($result) {
while ($r = mysql_fetch_array($result)) {

$Name
= $r["Name"];
$Email = $r["Email"];
$Phone = $r["Phone"];

### Rows ###
$data = "$Name,$Email,$Phone\n";
fwrite
($fp, $data);
}

echo
"A CSV file has been created.";

} else {

echo
"No data. There maybe an error in the database.";
}

fclose($fp);
mysql_free_result($result)

?>

Conclusion

Now that you have file creation under your belt you are ready to put this knowledge to use. You could use it to create CSS files on the fly, complex database backups via the web, or any number of other uses. Happy Coding!

No comments: