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:
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:
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