Học làm web (x6) - PHP: storing and retrieving data (tt)

Bài trước: Học làm web (x5) - PHP: storing and retrieving data
-----

Reading from a file (p65)


Right now, Bob’s customers can leave their orders via the Web, but if Bob’s staff members want to look at the orders, they have to open the files themselves.

Let’s create a web inteface to let Bob’s staff read the files easily. The code for this interface is shown below.

[vieworder.php]

<?php
    // create short variable name
    $document_root = $_SERVER['DOCUMENT_ROOT'];
?>
<!DOCTYPE html>
<html>
    <head>
        <title>Bob's Auto Parts - Order Results</title>
    </head>
    <body>
        <h1>Bob's Auto Parts</h1>
        <h2>Customer Orders</h2>
        <?php
            @$fp = fopen("$document_root/../orders/orders.txt", 'rb');
            flock($fp, LOCK_SH); // lock file for reading

            if(!$fp) {
                echo '<p><strong>No orders pending.<br>
                    Please try again later.</strong></p>';
                exit;
            }

            while (!feof($fp)) {
                $order = fgets($fp);
                echo htmlspecialchars($order).'<br>';
            }

            flock($fp, LOCK_UN); // release read lock
            fclose($fp);
        ?>
    </body>
</html>

This script follows the sequence we described earlier: open the file, read from the file, close the file. The output from this script is shown below:



Let’s look at the functions in this script in detail.

– Opening a file for reading: fopen()

   @$fp = fopen("$document_root/../orders/orders.txt", 'rb');

– Knowing when to stop: feof()

eof: end of the file

while (!feof($fp))

– Reading a line at a time: fgets(), fgetss(), fgetcsv()

In this example, you use the fgets() function to read from the file:

$order = fgets($fp);

This function reads one line at a time from a file. In this case, it reads until it encounters a newline character (\n) or EOF.

You can use many different functions to read from files. The fgets() function, for example, is useful when you’re dealing with files that contain plain text that you want to deal with in chunks.

An interesting variation on fgets() is fgetss(), which has the following prototype:

string fgetss(resource fp[, in length[, string allowable_tags]];

This function is similar to fgets() except that it strips out any PHP and HTML tags found in the string. If you want to leave in any particular tags, you can include them in the allowable_tags string. You would use fgetss() for safety when reading a file written by somebody else or one containing user input. Allowing unrestricted HTML code in the file could mess up your carefully planned formatting. Allowing unrestricted PHP or JavaScript could give a malicious user an opportunity to create a security problem.

The function fgetcsv() is another variation on fgets(). It has the following prototype:

array fgetcsv(resource fp, int length [, string delimiter
                        [, string enclosure
                        [, string escape]]])

This function breaks up lines of files when you have used a delimiting character, such as the tab character (as we suggested earlier), or a comma (as commonly used by spreadsheets and other applications). If you want to  reconsruct the variables from the order seperately rather than as a line of text, fgetcsv() allows you to do this simply. You call it in much the same way as you would call fgets(), but you pass it the delimiter you used to separate fields. For example,

$order = fgetcsv($fp, 0, ‘\t’);

This code would retrieve a line from the file and break it up wherever a tab (\t) was encountered.  The results are returned in an array.

The length parameter should be greater than the length in characters of the longest line in the file you are trying to read, or 0 if you do not want to limit the line length.

The enclosure parameter specifies what each field in a line is surrounded by. If not specified, it defaults to “ (a double quotation mark).

– Reading the whole file: readfile(), fpassthru(), file(), and file_get_contents()

Instead of reading from a file a line at a time, you can read the whole file in one go. Here are four different ways you can do this.

The first uses readfile(). You can replace almost the entire script you wrote previously with one line:

readfile("$document_root/../orders/orders.txt");

A call to the readfile() function opens the file, echoes the content to standard output (the browser), and then closes the file. The prototype for readfilne() is

int readfile (string filename, [bool use_include_path[, resource context]];

Second, you can use fpassthru(). To do so, you need to open the file using fopen() first. You can then pass the file pointer as an argument to fpassthru(), which dumps the contents of the file from the pointer’s position onward to standard output. It closes the file when it is finished.

You can use fpassthru() as follows:

$fp = fopen(("$document_root/../orders/orders.txt", ‘rb’);
fpassthru($fp);

The function fpassthru() returns true if the read is successful and false otherwise.

The third option for reading the whole file is using the file() function. This function is identical to readfile() except that instead of echoing the file to standard output, it turns it into an array.

$filearray = file((("$document_root/../orders/orders.txt");

This line reads the entire file into the array called $filearray. Each line of the file is stored in a separate element of the array.

The fourth option is to use the file_get_contents() function. This function is identical to readfile() except that it returns the content of the file as a string instead of outputing it to the browser.

– Reading a character: fgetc()

Another option for file processing is to read a single character at a time from a file. You can do this by using the fgetc() function. It takes a file pointer as its only parameter and returns the next character in a file. You can replace the while loop in the original script with one that uses fgetc(), as follows:

while (!feof($fp)){
            $char = fgetc($fp);
            if (!feof($fp))
                        echo ($char == “\n” ? “<br>” : $char);
}

Reading a file character by character is not generally sensible or efficient unless for some reason you actually want to process it character by character.

– Reading an arbitrary length: fread()

The final way you can read from a file is to use the fread() function to read an arbitrary number of bytes from the file. This function has the following prototype:

string fread(resource fp, int length);

It read up to length bytes, to the end of the file or network packet, whichever comes first.

Using other file functions (p70)


– Checking whether a file is there: file_exist()

If you want to check whether a file exists without actually opening it, you can use file_exist(), as follows:

if (file_exists("$document_root/../orders/orders.txt")) {
    echo 'There are orders waiting to be processed.';
} else {
    echo 'There are currently no orders.';
}

– Determining how big a file is: filesize()

You can check the size of a file by using the filesize() function:

echo filesize("$document_root/../orders/orders.txt");

– Deleting a file: unlink()

– Navigating inside a file: rewind(), fseek(), and ftell()

Locking files (p72)

A better way: Database (p73)


Problems with using flat files:

– When a file grows large, working with it can be very slow.

– Searching for a particular record or group of records in a flat file is difficult.

– Dealing with concurrent access can become problematic.

– All the file processing you have seen so far deals with a file using sequential processing.

– Beyond the limits offered by file permissions, there in no easy way of enforcing different levels of access to data.

How RDBMSs solve these problems

Relational database management systems address all these issues:

– RDBMSs can provide much faster access to data than flat files.

– RDBMSs can be easily queried to extract sets of data that fit certain criteria.

– RDBMSs have built-in machanisms for dealing with concurrent access so that you, as a programmer, don’t have to worry about it.

– RDBMSs provide random access to your data.

– RDBMSs have built-in privilege system.

Lab 10. Working with csv files

CSV stands for comma separated variable and indicates the file contains data delimited with a comma. Each line is a record, and each record is made up of fields, very much like a spreadsheet. In fact, software such as Excel provides the means to save files in this format. Note: You should using Notepad (saved as UTF-8) if you want to work with Vietnamese language. You can thinking about CSV file is a Excel file without header.

Using Excel to open employees.csv, as follows:



There are 3 lines of data, or records, in the file containing first name, last name, age and job title. To read the file and extract the individual fields, start by opening the file in read mode:

    $filename = 'employees.csv';
    $fp = fopen($filename, 'r';)

Now I need to use a function specifically to read the CSV formatted file, fgetcsv(); a while loop is used to cater for the for the fact that the number of records is expected to vary:

<?php
    $filename = 'employees.csv';
    $fp = fopen($filename, 'rb');
    while ($record = fgetcsv($fp)) {
        foreach($record as $field) {
            echo $field . '<br>';
        }
    }
    fclose($fp);
?>

This will produce output with a field on each line:

Nguyễn Văn
Tèo
30
Kỹ sư
Lê Văn
27
Lập trình viên
Trần
Dậu
40
Phân tích

Let’s examine the loop. First, fgetcsv() has one argument only  – the file handle; the comma delimiter is assumed. fgetcsv() returns data in an array which is then processed using a foreach loop. When all records have been read the file is closed using fclose().

Let’s now look at how you can update or write to a CSV file, this time using the function fputcsv(). Because I am using the same file that I used above, I will open it in append mode, and the data to be added to the file has been definied in an array.

// append data to the CSV file
    $newRecords  = array(
        array('Võ Thị', 'Sửu', 24, 'Kế toán'),
        array('Đặng', 'Dần', 24, 'Lập trình viên'),
        array('Lê', 'Ngọ', 45, 'Quản lý')
    );
    $fp = fopen($filename, 'a');
    foreach($newRecords as $record) {
        fputcsv($fp, $record);
    }
    fclose($fp);

Run above script, open the file employees.csv then to test the result.

</////06
-----------
Cập nhật [14/5/2019]
-----------
Xem thêm: Tổng hợp các bài viết về  Học làm web
Xem thêm: Học làm web (x7) - PHP: using arrays