Get up to 80 % extra points for free! More info:

Lesson 3 - Working with CSV files in PHP

In the previous lesson, Working with text files in PHP, we learned about a few basic single-purpose functions that we use in PHP to work with (not only) unstructured text files.

In this lesson, we'll learn about another way of working with files: by using resources. We'll also use our knowledge in the first practical example, where we'll work with structured text files in the CSV format.:-)

Working with files using resources

In the last lesson, we worked with the entire files. We read or wrote them whole in one function call. But PHP has another way to work with files, this time with more control over how the file is handled. Resources allow us to do that.

A resource, or also a handle, is a variable (or a data type) that stores information about the processed file - for example its descriptor, how many bytes we have already read, etc. It's only used to be passed to other functions that'll be performing actions with the file (reading, writing...) according to the state stored in this variable. This makes it possible to work with the same file in parts in several consecutive function calls. Other than that, resources can also be used to work with the online network.

Files are handled in the same way, in some other languages, for example in C, where the FILE structure plays the same role as a resource variable in PHP.

There are many functions for working with files this way. Since in our course we'll be working only with files in the CSV format, we'll get acquainted only with these 4 functions that are important to us:

fopen()

The fopen() function opens the file and returns a resource that we can use to continue working with the file. In case of an error, fopen() returns false. As the first argument, it takes a path to a file to be opened and as the second argument, a mode in which the file should be open:

$resource = fopen($path, $mode);

The mode is a one or two-character string that tells the function what we'll be doing with the file and how to open it. The most important modes are the following:

Mode Definition
r Opens the file for reading only.
r+ Opens the file for both reading and writing.
w Opens the file for writing only. If there is already any data in the file, it'll be cleared first. If the file does not exist, it'll be automatically created.
a Opens the file in append mode - if there is any data in the existing file, new data will be added to the end of the file. If the file does not exist, it'll be automatically created.

fgetcsv()

The fgetcsv() reads a row from a file, processes it as CSV, and returns the columns as an array of values. The only argument is the resource, which we obtained with fopen():

$csv_row = fgetcsv($resource);

If the resource we pass is invalid, this function returns a special NULL value. In the case of a different error, which will usually be caused by reaching the end of the file (so there is nothing to read), it returns false.

fputcsv()

The fputcsv() function takes the elements of an array passed as the second argument, converts them to the CSV format and writes the resulting string to a file whose resource is passed to the function as the first argument. The function returns the number of bytes written or false in case of an error:

$bytes_written = fputcsv($resource, $csv_row);

fclose()

The fclose() function closes the resource that we obtained with fopen(). We should never forget to close resources if they're no longer needed when working with files, otherwise, we may cause data loss! If successful, fclose() returns true, otherwise false.

$result = fclose($resource);

Simple To-Do list using a CSV file

We already know the names and the use cases of some important functions, so we can finally move on to working with CSV files. With their help, we'll create a simple task list.

We introduced CSV files in the introductory lesson of this course. These are structured text files where the stored values are separated by commas or semicolons. First, let's take a look at how our CSV database will look like:

"07/25/2020 12:36";normal;"go shopping"
"07/27/2020 18:02";high;"write an article on ICTdemy"
"07/30/2020 08:59";low;"fix my bike"

In the first column, we'll have the date and time when we added the task. In the second we'll have its priority. The third column is the most important thing – what we want to do:-)

HTML code of our application

First, we'll prepare the HTML code of our web gadget. It'll contain two basic parts:

  • a form for adding new tasks and
  • a table in which the entered tasks will be shown:
<?php
  // PHP code taking care of adding new tasks will be here
?>
<!DOCTYPE html>
<html>
  <head>
    <meta charset="UTF-8">
    <title>To-Do list</title>
  </head>
  <body>
    <h1>To-Do list</h1>

    <hr />

    <h3>New Task</h3>
    <form method="POST">
      <table>
        <tbody>
          <tr>
            <td>Task Description:</td>
            <td><input type="text" name="task_description" placeholder="Exercise, take out garbage..." size="50"></td>
          </tr>
          <tr>
            <td>Priority:</td>
            <td>
              <input type="radio" name="priority" value="high" checked>High
              <br />
              <input type="radio" name="priority" value="normal">Normal
              <br />
              <input type="radio" name="priority" value="low">Low
            </td>
          </tr>
        </tbody>
      </table>
      <input type="submit" value="Add">
    </form>

    <hr />

    <h3>My Tasks</h3>
    <table border="1">
      <thead>
        <tr>
          <th>Date and Time of Addition</th>
          <th>Priority</th>
          <th>Task Description</th>
        </tr>
      </thead>
      <tbody>
        <?php
            // PHP code reading the CSV file and outputting the table will be here
        ?>
      </tbody>
    </table>
  </body>
</html>

The output of this code is as follows:

To-Do list
01_todo.php

As we can see, the form has a text box named task_description and 3 radio buttons named priority. We'll use the information from these elements in our script for saving new tasks. The table where the tasks will be listed has 3 columns, just as our CSV file.

PHP code for saving tasks to CSV

Now we'll look at how the PHP code, that will save new tasks to the file, will look like:

$csv_with_tasks = "tasks.csv";

if($_SERVER["REQUEST_METHOD"] == "POST") {
  $resource = fopen($csv_with_tasks, "a"); // mode "a" - we're appending new data to the end of the file
  if(!$resource) { // successfully opened resource is always true
    echo "An error occurred while opening the CSV file!";
    exit();
  }

  $task = array(
    date("m/d/Y H:i"),
    $_POST["priority"],
    $_POST["task_description"]
  );

  if(fputcsv($resource, $task) === FALSE) { // saving the task into the file failed if fputcsv didn't return true
    echo "An error occurred while saving the new task to the CSV file!";
    exit();
  }

  if(!fclose($resource)) {
    echo "An error occurred while closing the CSV file!<br />";
    echo "Data might not be correctly saved!";
    exit();
  }
}

In the beginning, we defined a variable containing the name of our CSV file. We'll use this for both writing and reading. We then check if the HTTP method of POST was used by our form. If not, then our script was triggered by a request to load the page, so we'll not save any new task (because the user hasn't submitted anything yet) and we'll just display the page.

Otherwise, we first open the CSV file with the fopen() function in the a mode (because we do not want to delete previously recorded tasks) and store the resource returned by it in the $resource variable. Then we'll prepare an array $task with three elements, which will the fputcsv() function convert to the CSV format and write to the file. The first element will be the current date in the format mm/dd/YYYY HH:ii (see official documentation), the second will be the priority of the task (from the radio buttons named priority) and the third will be the description of the task (from the text field named task_description). Each element in the $task array represents one column in our CSV file. Then all we have to do is close the resource with the fclose() function.

If any function call fails, an appropriate error message will be displayed and script execution will be terminated immediately by the exit() function. This will cause that no additional PHP code will be executed or any HTML printed. Only the error message will be displayed.

PHP code for reading a CSV file and outputting the table

Now, we still need the code to read the CSV file and output the tasks to the table:

if(file_exists($csv_with_tasks)) {
  $resource = fopen($csv_with_tasks, "r");
  if(!$resource) {
    echo "An error occurred while opening the CSV file!";
    exit();
  }

  do {
    $task_array = fgetcsv($resource);
    if($task_array === NULL) {
      echo "CSV file was not opened successfully!";
      exit();
    }
    if($task_array === FALSE) { // most likely signalises that the end of the CSV file was reached
      break; // vyskočíme z nekonečné smyčky
    }

    echo "<tr>";
    foreach($task_array as $table_cell) { // outputs date and time, priority and task description
      echo "<td>", htmlspecialchars($table_cell, ENT_QUOTES), "</td>";
    }
    echo "</tr>";

  } while(TRUE);

  if(!fclose($resource)) {
    echo "An error occurred while closing the CSV file!";
    exit();
  }
}

Right at the beginning, we use the file_exists() function, which we have not talked about yet, but most of you already guessed that the function will find out whether the file whose path we pass to it exists or not and return the corresponding Boolean value.:-) We use the function so that the script does not try to list any tasks if the CSV file does not exist. The file is not created until the first task is written, and before we do so, we would be getting an error with the fopen() function, which would try to open a non-existent file for reading.

If the file exists, it is opened for reading by the fopen() function and then the script enters an "infinite" do-while loop. In the loop, the fgetcsv() function keeps reading lines from the CSV file and converting them into an array (each element of the array will contain one column of the CSV file). We'll then check if there was an error or if we reached the end of the file. In that case, we end the execution of the infinite cycle with the break statement. If all goes well, we'll output a new row of the table and data from the field into it so that each element of the field is listed as one column of the table. We won't forget to sanitize the output against the XSS attack with the htmlspecialchars() function. After outputting all tasks, we close the opened resource with the fclose() function.

Example

We're done:-) When we try to add some tasks, the content of the CSV file will look something like this:

"07/31/2020 13:21",normal,"Check e-mail mailbox"
"07/31/2020 13:22",high,"Go shopping"

The tasks will then be displayed in the browser as follows:

To-Do list
01_todo.php

If you had any problem with something, you can download the source code for the whole lesson below :)

In the next lesson, Working with XML files in PHP , we'll learn how to work with XML files. We will discuss the XMLWriter, XMLReader and SimpleXML classes.


 

Did you have a problem with anything? Download the sample application below and compare it with your project, you will find the error easily.

Download

By downloading the following file, you agree to the license terms

Downloaded 6x (1.98 kB)
Application includes source codes in language PHP

 

Previous article
Working with text files in PHP
All articles in this section
Working with files in PHP
Skip article
(not recommended)
Working with XML files in PHP
Article has been written for you by Jan Štěch
Avatar
User rating:
No one has rated this quite yet, be the first one!
As an author I'm interested in PHP for web development, I'm also trying to improve in C#
Activities