Richland College Multimedia Learning Center

Digital Media Programming with PHP and MySQL

Working with Files and Cookies in PHP

Opening Files

You can create and read files on the Web server with PHP. Please note that you can not create files on the user's computer.

Before you can write or read a file with PHP, you need to "open" it. The PHP function that opens a file is fopen( ).

Also, after you are finished with writing or reading a file, you need to "close" it. The PHP function that closes a file is fclose( ).

There are other PHP functions that you use to actually write and read the file. We will see some of these functions as we go through this handout.


File Handles

When you use fopen( ) to open a file, PHP returns an integer which is called a file handle. You need to save this file handle in a variable so you can use it to refer to the file as you work with it.

The syntax of fopen( ) is:

    $fp = fopen(<filename>,<access modifier>);

where:

The most common access modifiers are:

Modifier Type Description
"r" Read-only Your page can read from the file.
"w" Write Your page can write to the file. If the file already exists, its contents are overwritten.
"a" Append Your page can write to the end of the file.
"r+" "w+" Read and write This is called random access. Your page can read or write to any specified part of the file.

Please note that you need to very careful about opening a file in "write" mode. If you open an existing file in "write" mode, PHP actually creates a new file and overwrites (and destroys!) the original file. Sometimes this is the action that you want, but sometimes it is not. Be careful!


Writing to a File

The following sample code shows how you can write a file to the Web server. You can open/run this page here.

This is page saveSonnet.php:

<!DOCTYPE html>
<html>
<head>
  <meta charset="UTF-8">
  <link rel="stylesheet" href="myStyles.css">
  <title>SaveSonnet</title>
</head>

<body>
  <div id="mainDiv">
<?php

$sonnet76 = <<<HERE
Sonnet # 76, William Shakespeare

Why is my verse so barren of new pride,
So far from variation or quick change?
Why with the time do I not glance aside
To new-found methods, and to compounds strange?
Why write I still all one, ever the same,
And keep invention in a noted weed,
That every word doth almost tell my name,
Showing their birth, and where they did proceed?
O! know sweet love I always write of you,
And you and love are still my argument;
So all my best is dressing old words new,
Spending again what is already spent:
For as the sun is daily new and old,
So is my love still telling what is told.

HERE;

$fp = fopen("sonnet76.txt", "w");
if ($fp === false)
{
	echo "<h3>Your file is not accessible!</h3>\n";
}
else
{
	$numBytes = fputs($fp, $sonnet76);
	fclose($fp);
	if ($numBytes === false)
	{
		echo "<h3>Nothing was written!</h3>\n";
	}
	else
	{
		echo "<h3>The sonnet was saved!</h3>\n";
	}
}
?>
  </div>
</body>
</html>

Please note these points about the above code:


Reading from a File

If you open a file with the "r" access modifier, you can read information from that file.

The following sample code shows how you can read a file from the Web server.

This is page loadSonnet.php:

<!DOCTYPE html>
<html>
<head>
  <meta charset="UTF-8">
  <link rel="stylesheet" href="myStyles.css">
  <title>LoadSonnet</title>
  <style type="text/css">
    body
    {
      background-color:darkred;
      color:white;
      font-family:Arial, sans-serif;
      font-style: italic;
      font-size:2em;
    }
    #mainContents
    {
      text-align: center;
    }
  </style>
</head>

<body>
<div id="mainContents">
<?php
error_reporting(0);
$fp = fopen("sonnet76.txt", "r");

if ($fp !== false)  // fopen was successful
{
  //first line is title
  $line = fgets($fp);
  print "<h1>$line</h1>\n";
  
  //print rest of sonnet
  while (!feof($fp)){
    $line = fgets($fp);
    print "$line <br />\n";
  } // end while
  
  fclose($fp);
}
else
{
  echo "<h3>We're sorry, we could not find your sonnet.</h3>\n";
}
?>
</div>
</body>
</html>

You can see how the file looks after it has been read from the server's hard drive and displayed in an HTML page, here.

Please note these points about the above code:


You may be asking yourself, "What happens if the file isn't on the server's hard drive?"

Part of the answer is given in the fourth point in the list above: fopen( ) returns FALSE if it does not find the file that you are trying to open.

The following sample code is pretty much the same as the previous sample. But it has two interesting additions:

  1. The code
    error_reporting(0);
    tells PHP not to display any error messages. If you don't tell PHP to be quiet, PHP will put an ugly error message into your page even if you handle the missing file correctly.
  2. The code
    if ($fp)
    {
    starts a conditional block of code that is executed only if the file was opened. This is what I meant in the previous point about handling the missing file correctly.

This is page loadSonnet2.php:

<!DOCTYPE html>
<html>
<head>
  <meta charset="UTF-8">
  <link rel="stylesheet" href="myStyles.css">
  <title>LoadSonnet 2</title>
  <style type="text/css">
    body
    {
      background-color:darkred;
      color:white;
      font-family:Arial, sans-serif;
      font-style: italic;
      font-size:2em;
    }
    #mainContents
    {
      text-align: center;
    }
  </style>
</head>

<body>
<div id="mainContents">
<?php
error_reporting(0);
$fp = fopen("sonnet76b.txt", "r");

if ($fp)
{
  //first line is title
  $line = fgets($fp);
  print "<h1>$line</h1>\n";
  
  //print rest of sonnet
  while (!feof($fp)){
    $line = fgets($fp);
    print "$line <br />\n";
  } // end while
  
  fclose($fp);
}
else
{
  echo "We're sorry, we could not find your sonnet.";
}
?>
</div>
</body>
</html>

Please note these additional points about the above code:

You can see how the page looks when the file is not opened, here.


Reading a File into an Array

Sometimes it is useful to read an entire file into the server's memory, into an array, and to manipulate the file's contents in the array.

The following sample code shows how to read a file into an array. It also shows a simple search and replace operation on the file's contents.

In the following sample page, an HTML "template" is read into the array. Then some known, special strings are replaced in order to "personalize" the page. Please note that there are other ways to "personalize" a page. This is just one way to do it.

This is the "template" file, statusReport.html:

<!DOCTYPE html>
<html>
<head>
  <meta charset="UTF-8">
  <link rel="stylesheet" href="myStyles.css">
  <title>Status Report</title>
  <style type="text/css">
    body {font-family: Arial, sans-serif; }
    table { border: 1px solid gray; border-collapse: collapse; }
    td, th { border: 1px solid gray; padding: 5px; }
  </style>
</head>

<body>
  <div id="mainDiv">
    <p>
      This is a status report for @@@NAME@@@.
    </p>
    <table>
      <tr>
        <th>Department</th>
        <th>Status</th>
      </tr>
      <tr>
        <td>Engineering</td>
        <td>@@@ENG@@@</td>
      </tr>
      <tr>
        <td>Supply</td>
        <td>@@@SUPP@@@</td>
      </tr>
      <tr>
        <td>Operations</td>
        <td>@@@OPS@@@</td>
      </tr>
      <tr>
        <td>Personnel</td>
        <td>@@@PERS@@@</td>
      </tr>
    </table>
  </div>
</body>
</html>

This is the page which reads and modifies the "template" page. It is personalize.php:

<?php
$fileName = "statusReport.html";

$statusReport = file($fileName);
$output = "";

foreach ($statusReport as $currentLine){
  $currentLine = str_replace("@@@NAME@@@", "Captain Rodriguez", $currentLine);
  $currentLine = str_replace("@@@ENG@@@", "Ready", $currentLine);
  $currentLine = str_replace("@@@SUPP@@@", "Ready", $currentLine);
  $currentLine = str_replace("@@@OPS@@@", "On Standby", $currentLine);
  $currentLine = str_replace("@@@PERS@@@", "On Standby", $currentLine);
  $output .= rtrim($currentLine) . "\n";
} // end foreach

print $output;

?>

Please note these points about the above code:

You can see how the report page looks after it has been searched and replaced here.

There is an alternative syntax which you can use for the str_replace() function, which uses arrays as its arguments. This alternative page, which also reads and modifies the "template" page, is personalize2.php:

<?php
$fileName = "statusReport.html";

$statusReport = file($fileName);
$output = "";

$needleArray = array("@@@NAME@@@","@@@ENG@@@","@@@SUPP@@@","@@@OPS@@@","@@@PERS@@@");
$replaceArray = array("Captain Rodriguez","Ready","Ready","On Standby","On Standby");

$statusReport = str_replace($needleArray, $replaceArray, $statusReport);

foreach ($statusReport as $currentLine){
  $output .= rtrim($currentLine) . "\n";
} // end foreach

print $output;

?>

Please note these points about the above code:

You can see how the second report page looks after it has been searched and replaced here.


Getting Directory Information

Sometimes when you are working with files on the server, you need to work with the directory structure that contains the files.

The following sample code shows how you can get a listing of image files in a directory and make a basic index of the image files.

This is file imageIndex.php:

<!DOCTYPE html>
<html>
<head>
  <meta charset="UTF-8">
  <link rel="stylesheet" href="myStyles.css">
  <title>imageIndex</title>
</head>
<body>
  <div id="mainDiv">
<?php

// image index
// generates an index file containing all images in a particular directory

//point to whatever directory you wish to index.
//index will be written to the program file's directory as imageIndex.html
$dirName = getcwd() . "/images";
$dp = opendir($dirName);
chdir($dirName);

//add all files in directory to $theFiles array
$currentFile = readDir($dp);
while ($currentFile !== false){
	print($currentFile) . "<br>";
  $theFiles[] = $currentFile;
  $currentFile = readDir($dp);
} // end while

//extract gif and jpg images
$imageFiles = preg_grep("/jpg$|gif$/", $theFiles);
$output = "<!DOCTYPE html>\n<html>\n<head>\n  <meta charset='UTF-8'>\n  <link rel='stylesheet' href='myStyles.css'>\n  <title>imageIndex</title>\n</head>\n<body>\n  <div id='mainDiv'>\n";
foreach ($imageFiles as $currentFile){
  $output .= <<<HERE
<a href="images/$currentFile"><img src = "images/$currentFile" border="0" height = "50" width = "50"></a> 
HERE;
} // end foreach
$output .= "\n  </div>\n</body>\n</html>";
//save the index to the local file system
chdir("../");
$fp = fopen("imageIndex.html", "w");
if ($fp === false)
{
	echo "<h3>Your file is not accessible!</h3>\n";
}
else
{
  $numBytes = fputs($fp, $output);
  fclose($fp);
  if ($numBytes === false)
  {
    echo "<h3>Nothing was written!</h3>\n";
  }
  else
  {
    print "\n<br>\n<a href='imageIndex.html'>image index</a>\n";
  }
}
//readFile("imageIndex.html");
?>
  </div>
</body>
</html>

You can see what the image index looks like here.

Please note these points about the above code:


Working with Formatted Text

Text files, such as the sonnet file that we saw earlier in this handout, are very easy to work with. But they are very unstructured. Sometimes it is better to have some structure (also called formatting) in your files.

For instance, we can make a mailing list file that uses tabs to mark, or delimit, the information fields in the file. Here is what such a tab-delimited file might look like: (You will not see the tabs in the listing below. There is a tab character after the name, between the name and the e-mail address.) This is file maillist.dat:

Santa Clause  santa@northpole.com
Elvis elvis@graceland.com
ET  et@home.univ

The following page shows how you can use the maillist.dat file to create some personalized letters. This is file mailMerge.php:

<!DOCTYPE html>
<html>
<head>
  <meta charset="UTF-8">
  <link rel="stylesheet" href="myStyles.css">
  <title>Mailing List</title>
</head>
<body>
  <div id="mainDiv">
<?php
//Simple Mail merge
//presumes tab-delimmited file called maillist.dat

$theData = file("maillist.dat");



foreach($theData as $line){
  $line = rtrim($line);
  print "<h3>$line</h3>";
  list($name, $email) = explode("\t", $line);
  print "Name: $name";

  $message = <<<HERE
TO: $email:
Dear $name:

Thanks for being a part of the spam afficianado forum.
You asked to be notified whenever a new recipe was posted.
Be sure to check our web site for the delicious
'spam flambe with white sauce and cherries' recipe.

Sincerely,

Sam Spam,
Host of Spam Afficianados.

HERE;


  print "<pre>$message</pre>";

} // end foreach
?>
  </div>
</body>
</html>

You can see what the form "letters" look like here.

Please note these points about the above code:


Using Include Files

Sometimes it is advantageous to store code that you will be using in multiple Web pages, in a separate file called an "include file". You can "include" the code that is in this "include file", in each page that you need it in.

You should note carefully that the PHP processor adds the code that is in the "include file" to the code that it is processing for that page, and processes it, as if the code that is in the "include file" were actually typed into that page.

When a file is included, the code it contains inherits the variable scope of the line on which the include occurs. Any variables available at that line in the calling file will be available within the called file, from that point forward. However, all functions and classes defined in the included file have the global scope.

When a file is included, parsing drops out of PHP mode and into HTML mode at the beginning of the target file, and resumes again at the end. For this reason, any code inside the target file which should be executed as PHP code must be enclosed within valid PHP start and end tags.

The syntax of the "include" statement that goes in the page that is including and using the code in the "include file" looks like this:

include "<filename>";

There is a related statement, called require, that functions like include but throws a fatal error if the included file is not available. The include statement throws a warning, but not an error, if the included file is not available.

Here is a sample of a file that uses an "include file". This is page testInclude.php:

<!DOCTYPE html>
<html>
<head>
  <meta charset="UTF-8">
	<title>Test a PHP Include File</title>
  <link rel="stylesheet" href="myStyles.css">
</head>

<body>
  <div id="mainDiv">
    <?php
    error_reporting (E_ERROR | E_WARNING | E_PARSE | E_NOTICE);
    echo "<h3>Here is the bad stuff:</h3>";
    echo "<p>";
    echo "A $color $fruit"; // A
    echo "</p>";
    
    include 'vars.php';
    
    echo "<h3>Here is the good stuff:</h3>";
    echo "<p>";
    echo "A $color $fruit";
    echo "</p>";
    
    ?>
  </div>
</body>
</html>

Here is the "include file", vars.php:

<?php

$color = 'green';
$fruit = 'apple';

?>

You can see the sample include file running here.

Please note these points about the above code:


Uploading a File

When you first learned HTML, you probably heard someone (such as the instructor) tell you that the <input type="file" /> form field was pretty much useless unless you could use a server-side process to manage a file upload. With PHP you have that server-side process!

Here are some HTML and PHP hints and instructions regarding file uploads:

Here is a sample HTML form that will start the file upload process. (Please note that the form's action page is a PHP page.) This form page is fileUploadForm.html:

<!DOCTYPE html>
<html>
<head>
  <meta charset="UTF-8">
  <link rel="stylesheet" href="myStyles.css">
  <title>Form to Upload a File</title>
</head>

<body>
  <div id="mainDiv">
    <!-- The data encoding type, enctype, MUST be specified as below -->
    <form enctype="multipart/form-data" action="fileUploadAction.php" method="post">
      <!-- MAX_FILE_SIZE must precede the file input field -->
      <input type="hidden" name="MAX_FILE_SIZE" value="30000">
      <!-- Name of input element determines name in $_FILES array -->
      Send this file:
      <br>
      <input name="userfile" size="60" type="file">
      <br>
      <br>
      <input type="submit" value="Send the File">
    </form>
  </div>
</body>
</html>

Here is the PHP action page. It displays the $_FILES array just for informational purposes, which you probably would not do in the real world. It also moves the uploaded file to a directory called tmp. This is page fileUploadAction.php:

<!DOCTYPE html>
<html>
<head>
  <meta charset="UTF-8">
  <link rel="stylesheet" href="myStyles.css">
  <title>Action Page for File Upload</title>
</head>

<body>
  <div id="mainDiv">
    <?php
      echo "<h4>Array \$_FILES:</h4>\n";
      echo "<pre>";
      print_r($_FILES);
      echo "</pre>";
  
    $target_path = "tmp/";
    $baseFileName = basename( $_FILES['userfile']['name']);
    
    $target_path = $target_path . $baseFileName; 
    if(move_uploaded_file($_FILES['userfile']['tmp_name'], $target_path))
    {
      echo "<p>The file " . $baseFileName . 
      " has been uploaded to $target_path</p>";
    }
    else
    {
      echo "<h4>There was an error uploading file " . 
      $baseFileName . "</h4>";
      switch ($_FILES['userfile']['error'])
      {
        case 2: $errorDescr = "The uploaded file exceeds the MAX_FILE_SIZE directive that was specified in the HTML form.";
        break;
        
        case 3: $errorDescr = "The uploaded file was only partially uploaded.";
        break;
        
        case 4: $errorDescr = "No file was uploaded.";
        break;
        
        case 6: $errorDescr = "Missing a temporary folder.";
        break;
        
        case 7: $errorDescr = "Failed to write file to disk.";
        break;
        
        case 8: $errorDescr = "File upload stopped by extension.";
        break;
        
        default: $errorDescr = "There was an unknown error code.  The code was " . strval($_FILES['userfile']['error']) . ".";
      }
      echo "<p>$errorDescr</p>";
    }
  ?>
  </div>
</body>
</html>

You can see the file upload form and its PHP action page here.

Please note these points about the above code:


Cookies

You can use cookies to communicate information from one page to another, or even back to the current page. Cookies are just one of several options you have to send this information to the next page. You have already seen how you can use session variables to do the same thing.

The main advantage of cookies is that you can set a cookie to remain on the user's hard-drive storage for a specified time period. This feature of cookies means that the information will be there the next time the user loads your page, even if they have closed the browser since the last time they loaded your page.

If you do give the cookie an expiration time, the cookie is referred to as a persistent cookie.

If you don't give the cookie an expiration time, it will stay in the memory of the user's computer only as long as the browser is kept open. When the browser is closed, the cookie is deleted from the computer's memory. This kind of cookie is referred to as a transient cookie.

You use the PHP built-in function setcookie() to define a cookie to be sent to the Web server along with the rest of the HTTP headers. Like other headers, cookies must be sent before any output from your script (this is a protocol restriction). This restriction requires that you place calls to this function prior to any output, including <html> and <head> tags as well as any whitespace.

The syntax of setcookie() is shown below in simplified form. (The syntax in the PHP Function Reference has a lot more information that you can read later if you need it.)

  setcookie ($cookie_name [, $cookie_value [, $expire_time = 0 ]])

Please note these points about the above function syntax:

After the cookie has been set, you can get the information that is in the cookie by using the $_COOKIE associative array. Please note, though, that the cookie will be available in the $_COOKIE array at the next page load after the cookie is set.


A Transient Cookie

Here are some pages that allow you to put your name into a transient cookie.

If you close this browser and the browser window that displays the value of the transient cookie, re-open a browser and get back to this handout, and then you open the page that reads the cookie again, the cookie will not be there. The cookie is transient.

The pages that handle the transient cookie are shown below. The first page is setCookieForm.html:

<!DOCTYPE html>
<html>
<head>
  <meta charset="UTF-8">
  <link rel="stylesheet" href="myStyles.css">
  <title>Set a Cookie Form</title>
  <script type="text/javascript">
    function positionCursor()
    {
      document.getElementById("yourName").focus();
    }
  </script>
</head>

<body onload="positionCursor();">
  <div id="mainDiv">
    <h3>Set a Cookie</h3>
    <form method="post" action="setCookieAction.php">
      Type your name:
      <input type="text" name="yourName" id="yourName" />
      <br />
      <br />
      <input type="submit" value="Set the Cookie" />
    </form>
  </div>
</body>
</html>

The form's action page, which sets the transient cookie, is setCookieAction.php:

<?php
  if (isset($_POST["yourName"]))
  {
    setcookie("TestCookie", $_POST["yourName"]);
  }
?>
<!DOCTYPE html>
<html>
<head>
  <meta charset="UTF-8">
  <link rel="stylesheet" href="myStyles.css">
  <title>Set a Cookie Form</title>
</head>

<body>
  <div id="mainDiv">
    <h3>The transient cookie has been set!</h3>
    <a href="readCookie.php">Read the Transient Cookie</a>
  </div>
</body>
</html>

The page that reads and displays the transient cookie is readCookie.php:

<!DOCTYPE html>
<html>
<head>
  <meta charset="UTF-8">
  <link rel="stylesheet" href="myStyles.css">
  <title>Read the Cookie</title>
</head>

<body>
  <div id="mainDiv">
    <h3>Read a Transient Cookie</h3>
    <?php
      if (isset($_COOKIE["TestCookie"]))
      {
        $cookieValue = $_COOKIE["TestCookie"];
      }
      else
      {
        $cookieValue = "Unknown";
      }
      echo "The Transient Cookie's value is '" . $cookieValue . "'.";
    ?>
  </div>
</body>
</html>

A Persistent Cookie

Here are some pages that allow you to put your name into a persistent cookie.

If you close this browser and the browser window that displays the value of the persistent cookie, re-open a browser and get back to this handout, and then you open the page that reads the cookie again, the cookie will be there. This cookie is persistent.

The pages that handle the persistent cookie are shown below. The first page is setCookieForm2.html:

<!DOCTYPE html>
<html>
<head>
  <meta charset="UTF-8">
  <link rel="stylesheet" href="myStyles.css">
  <title>Set a Cookie Form</title>
  <script type="text/javascript">
    function positionCursor()
    {
      document.getElementById("yourName").focus();
    }
  </script>
</head>

<body onload="positionCursor();">
  <div id="mainDiv">
    <h3>Set a Persistent Cookie</h3>
    <form method="post" action="setCookieAction2.php">
      Type your name:
      <input type="text" name="yourName" id="yourName" />
      <br />
      <br />
      <input type="submit" value="Set the Persistent Cookie" />
    </form>
  </div>
</body>
</html>

The form's action page, which sets the persistent cookie, is setCookieAction2.php:

<?php
  if (isset($_POST["yourName"]))
  {
    setcookie("TestCookie2", $_POST["yourName"], time()+3600);  /* expire in 1 hour */
  }
?>
<!DOCTYPE html>
<html>
<head>
  <meta charset="UTF-8">
  <link rel="stylesheet" href="myStyles.css">
  <title>Set a Persistent Cookie Form</title>
</head>

<body>
  <div id="mainDiv">
    <h3>The persistent cookie has been set!</h3>
    <a href="readCookie2.php">Read the Persistent Cookie</a>
  </div>
</body>
</html>

The page that reads and displays the persistent cookie is readCookie2.php:

<!DOCTYPE html>
<html>
<head>
  <meta charset="UTF-8">
  <link rel="stylesheet" href="myStyles.css">
  <title>Read the Cookie</title>
</head>

<body>
  <div id="mainDiv">
    <h3>Read a Persistent Cookie</h3>
    <?php
      if (isset($_COOKIE["TestCookie2"]))
      {
        $cookieValue = $_COOKIE["TestCookie2"];
      }
      else
      {
        $cookieValue = "Unknown";
      }
      echo "The Persistent Cookie's value is '" . $cookieValue . "'.";
    ?>
  </div>
</body>
</html>