Học làm web (x8) - PHP: sorting arrays

Bài trước: Học làm web (x7) - PHP: using arrays
-----

Array operatiors (p81)


Operator

Name

Example

Result

+

Union

$a + $b

Union of $a and $b. The array $b is appended to $a, but any key clashed are not added.

=

Equality

$a == $b

True if $a and $b contain the same elements.

===

Identity

$a === $b

True if $a and $b contain the same elements, with the same types, in the same order.

!=

inequality

$a != $b

True if $a and $b do not contain the same elements.

<> 

inequality

$a <> $b

Same as !=

!==

Non-identity

$a !== $b

True if $a and $b do not contain the same elements, with the same types, in the same order.


Multidimensional arrays (p82)


You can think of a two-dimentional array as a matrix, or grid, with width and height or rows and columns.

If you want to store more than one piece of data about each of Bob’s products, you could use a two-dimentional array. Table below shows Bob’s products represented as a two-dimentional array with each row representing an individual product and each column representing a stored product attribute.

product >
Code
Description
Price
TIR
Tires
100
OIL
Oil
10
SPK
Spark Plugs
4
Product attribute >

Using PHP, you would write the following code to set up the data in the array shown in above table:

$products = array( array(‘TIR’, ‘Tires’, 100),
                        array(‘OIL’, ‘Oil’, 10),
                        array(‘SPK’, ‘Spark Plugs’, 4));

You can see from this definition that the $products array now contains three arrays.

To access the data in a two-dimentional array you need the name of the array and two indices: a row and a column.

To display the contents of this array, you could manually access each element in order like this:

echo '|'.$products[0][0].'|'.$products[0][1].'|'.$products[0][2].'|<br>';
echo '|'.$products[1][0].'|'.$products[1][1].'|'.$products[1][2].'|<br>';
echo '|'.$products[2][0].'|'.$products[2][1].'|'.$products[2][2].'|<br>';

Alternatively, you could place a for loop inside another for loop to achieve the same result:

for ($row = 0; $row < 3; $row++) {
for ($column = 0; $column < 3; $column++) {
echo '|'.$products[$row][$column];
}
echo '|<br>';
}

Both versions of this code produce the same output in the browser:

|TIR|Tires|100||OIL|Oil|10|
|SPK|Spark Plugs|4|

You might prefer to create column names instead of numbers, you would use the following code:

$products = array(array('Code' => 'TIR',
'Description' => 'Tires',
'Price' => 100
),
array('Code' => 'OIL',
'Description' => 'Oil',
'Price' => 10
),
array('Code' => 'SPK',
'Description' => 'Spark Plugs',
'Price' =>4
)
);

This array is easier to work with if you want to retrieve a single value. Remembering that the description is stored in the Description column is easier than remembering it is stored in column 1. Using descriptive indices, you do not need to remember that an item is stored at [x][y]. You can easily find your data by referring to a location with meaningful row and column names.

You do, however, lose the ability to use a simple for loop to step through each column in turn. Here is one way to write code to display this array:

for ($row = 0; $row < 3; $row++){
echo '|'.$products[$row]['Code'].'|'.$products[$row]['Description'].
'|'.$products[$row]['Price'].'|<br />';
}

Using a for loop, you can step through the outer, numerically indexed $products array. Each row in the $products array is an array with descriptive indices. Using the each() and list() functions in a while loop, you can step through these inner arrays. Therefore, you can use a while loop inside a for loop:

for ($row = 0; $row < 3; $row++){
while (list( $key, $value ) = each( $products[$row])){
echo '|'.$value;
}
echo '|<br />';
}   

Three dimentional arrays (p84)


Sorting Arrays (p85)


Sorting related data stored in an array is often useful. You can easily take a one-dimentional array and sort it into order.

Using sort()

The following code showing the sort() function results in the array being sorted into ascending alphabetical order:

$products = array('Tires', 'Oil', 'Spark Plugs');
sort($products);

You can sort values by numerical order too.

$prices = array(100, 10, 4);
sort($prices);

Note that the sort() function is case sensitive. All capital letters come before all lowercase letters. So A is less than Z, but Z is less than a.

The function also has an optional second parameter. You may pass one of the constants SORT_REGULAR (the default), SORT_NUMERIC, SORT_STRING, SORT_LOCALE_STRING, SORT_NATURAL, SORT_FLAG_CASE.

The ability to specify the sort type is useful when you are comparing strings that might contain numbers, for example, 2 and 12. Numerically, 2 is less than 12, but as strings ‘12’ is less than ‘2’.

Using asort() and ksort to sort arrays (p86)

If you are using an array with descriptive keys to store items and their prices, you need to use different kinds of sort functions to keep keys and values together as they are sorted.

The following code creates an array containing the three products and their associated prices and then sorts the array into ascending price order:

$prices = array('Tires'=>100, 'Oil'=>10, 'Spark Plugs'=>4);
asort($prices);

The function asort() orders the array according to the value of each element. In the array, the values are the prices, and the keys are the textual descriptions. If, instead of sorting by price, you want to sort by description, you can use ksort(), which sorts by key rather than value.

The following code results in the keys of the array being ordered alphabetically: Oil, Spark Plugs, Tires:

$prices = array('Tires'=>100, 'Oil'=>10, 'Spark Plugs'=>4);
ksort($prices);

Sorting in Reverse (p87)

The three different sorting functions––sort(), asort(), and ksort()––sort an array into ascending order. Each function has a matching reverse sort function to sort an array into descending order. The reverse versions are called rsort(), arsort(), and krsort().


Sorting multidimensional arrays (p87)


Sorting arrays with more than one dimension, or by something other than alphabetical or numerical order, is more complicated. PHP knows how to compare two numbers or two text strings, but in a multidimensional array, each element is an array.

There are two approaches to sorting multidimensional arrays: creating a user-defined sort or using the array_multisort() function.

Using the array_multisort() function

The array_multisort() function can be used either to sort multidimensional arrays, or to sort multiple arrays at once.

The following is the definition of a two-dimensional array used earlier. This array stores Bob’s three products with a code, a description, and a price for each:

$products = array(array('TIR', 'Tires', 100),
array('OIL', 'Oil', 10),
array('SPK', 'Spark Plugs', 4));

If we simply take the function array_multisort() and apply it as follows, it will sort the array. But in what order?

array_multisort($products);

As it turns out, this will sort our $products array by the first item in each array, using a regular ascending sort, as follows:

'OIL', 'Oil', 10
'SPK', 'Spark Plugs', 4
'TIR', 'Tires', 100

This function has the following prototype:

bool array_multisort(array &a [, mixed order = SORT_ASC [, mixed sorttype =
SORT_REGULAR [, mixed $... ]]] )

For the ordering you can pass SORT_ASC or SORT_DESC for ascending or descending order, respectively.

For the sort type, array_multisort() supports the same constants as the sort() function.

One important point to note for array_multisort() is that, while it will maintain key-value association when the keys are strings, it will not do so if the keys are numeric, as in this example.

User-defined sorts (p88)

Reverse user sorts (p89)


Reordering arrays (p90)


For some applications, you might want to manipulate the order of the array in other ways than a sort. The function shuffle() randomly reorders the elements of your array. The function array_reverse() gives you a copy of your array with all the elements in reverse order.

Using shuffle()

Bob wants to feature a small number of his products on the front page of his site. He has a large number of products but would like three randomly selected items shown on the front page. So that repeat visitors do not get bored, he would like the three chosen products to be different for each visit. He can easily accomplish his goal if all his products are in an array. Solution is shuffling the array into a random order and then displaying the first three.

Lab 12. Using PHP to produce a dynamic front page for Bob’s auto parts.

<?php
$pictures = array('brakes.png', 'headlight.png',
'spark_plug.png', 'steering_wheel.png',
'tire.png', 'wiper_blade.png');
shuffle($pictures);
?>
<!DOCTYPE html>
<html>
<head>
<title>Bob's Auto Parts</title>
</head>
<body>
<h1>Bob's Auto Parts</h1>
<div align="center">
<table style="width: 100%; border: 0">
<tr>
<?php
for ($i = 0; $i < 3; $i++) {
echo "<td style=\"width: 33%; text-align: center\">
<img src=\"";
echo $pictures[$i];
echo "\"/></td>";
}
?>
</tr>
</table>
</div>
</body>
</html>


Reversing an array (p92)

</////08
-----------
Cập nhật [21/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 (x9) - PHP: 

Học làm web (x7) - PHP: using arrays

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

1.3            Using arrays


An array is a variable that stores a set or sequence of values. One array can have many elements, and each element can hold a single value, such as text or numbers, or another array. An array containing other arrays is known as a multidimention array.

PHP supports arrays with both numerical and string indexes.

Numerically indexed arrays (p76)


To create the array with numerical index, use the following line of PHP code:

$products = array(‘Tires’, ‘Oil’, ‘Spark Plugs’);

Since PHP 5.4, you can use a new shorthand syntax for creating arrays. This uses the [ and ] characters in place of the array() operator. For example,

$products = [‘Tires’, ‘Oil’, ‘Spark Plugs’];

Depending on the contents you need in your array, you might not need to manually initialize them as in the preceding example. If you have the data you need in another array, you can simply copy one array to another using the = operator.

If you want an ascending sequence of numbers stored in an array, you can use the range() function to automatically create the array for you. The following statement creates an array called numbers with elements ranging from 1 to 10.

$numbers = range(1, 10);

The range() function has an optional third parameter that allows you to set the step size between values. For instance, if you want an array of the odd numbers between 1 and 10, you could create it as follows:

$odds = range(1, 10, 2);

The range() function can also be used with character, as in this example:

$letters = range(‘a’, ‘z’);

If you have information stored in a file on disk, you can load the array contents directly from the file.
If you have the data for your array stored in a database, you can load the array contents directly from the database.

You can also use various functions to extract part of an array or to reorder an array.

Accessing array contents (p77)

To access the contents of a variable, you use its name. If the variable is an array, you access the contents using both the variable name and a key or index. The key or index indicates which of the values in the array you access. The index is placed in square brackets after the name. In other words, you can use $products[0], $products[1], and $products[2] to access each of the contents of the $products array.

You may also use the {} characters to access array elements instead of the [] characters if you prefer. For example, you could use $products{0} to access the first element of the products array.

By default, element zero is the first element in the array.

As with other variables, you change array elements’ contents by using the = operator. The following line replaces the first element in the array, ‘Tires’, with ‘Fuses’:

$products[0] = ‘Fuses’;

To display the contents, you could type this line:

echo “$products[0] $products[1] $products[2]”;

Like other PHP variables, arrays do not need to be initialized or created in advance. They are automatically created the first time you use them.

The following code creates the same $products array created previously with array() statement:

$products[0] = “Tires”;
$products[1] = “Oil”;
$products[2] = “Spark Plugs”;

If $products does not already exist, the first line will create a new array with just one element. The subsequent lines add values to the array. The array is dynamically resized as you add elements to it. This resizing capability is not present in many other programming languages.

Using loops to access the array (p78)

for ($i = 0; $i<3; $i++) {
echo $products[$i]." ";
}

You can also use the foreach loop, specially designed for use with arrays. In this examply, you could use it as follows:

foreach ($products as $current) {
echo $current." ";
}

Arrays with different indices (p79)


Initializing an array

The following code creates an array with product names as keys and prices as values:

$prices = array(‘Tires’ => 100, ‘Oil’ => 10, ‘Spark Plugs’ => 4);

The symbol between the keys and values (=>) is simply an equal sign immediately followed by a greater than symbol.

Accessing the array elements

Again, you access the contents using the variable name and a key, so you can access the information stored in the prices array as $prices[‘Tires’], $prices[‘Oil’], $prices[‘Spark Plugs’].

The following code creates the same $prices array. Instead of creating an array with three elements, this version creates an array with only one element and then adds two more:

$prices = array(‘Tires’ => 100);
$prices[‘Oil’] = 10;
$prices[‘Spark Plugs’] = 4;

Here is another slightly different but equivalent piece of code. In this version, you do not explicitly create an array at all. The array is created for you when you add the first element to it:

$prices[‘Tires’] = 100;
$prices[‘Oil’] = 10;
$prices[‘Spark Plugs’] = 4;

Using loops

Because the indices in an array are not numbers, you cannot use a simple counter in a for loop to work with the array. However, you can use the foreach loop or the list() and each() constructs.

foreach($prices as $key => $value) {
            echo $key. “ - ”.$value.“<br>”;
}

The following code lists the contents of the $prices array using the each() construct:

while ($element = each($prices)) {
            echo $element[‘key’].“ - ”.element[‘value’];
            echo “<br>”;
}

each() function returns the current element in an array and makes the next element the current one. Because we are calling each() within a while loop, it returns every element in the array in turn and stops when the end of the array is reached.

In this code, the variable $element is an array. When you call each(), it gives you an array with four values and the four indices to the array locations. The location key and 0 contain the key of the current element, and the locations value and 1 contain the value of the current element. Although the one you choose makes no difference, we chose to use the named locations rather than the numbered ones.

There is a more element and common way of doing the same thing. The construct list() can be used to split an array into a number of values. You can separate each set of values that the each() function give you like this:

while (list($product, $price) = each($prices)) {
            echo $product.“ – ”.$price.“<br>”;
}

This line uses each() to take the current element from $prices, return it as an array, and make the next element current. It also uses list() to turn the 0 and 1 elements from the array returned by each() into two new variables called $product and $price.

When you are using each(), note that the array keeps track of the current element. If you want to use the array twice in the same script, you need to set the current element back to the start of the array using the function reset(). To loop through the prices array again, you type the following:

reset($prices);
while (list($product, $price) = each($prices)) {
            echo $product.“ – ”.$price.“<br>”;
}

Lab 11. Create a Select Box.

Create a Select Box by using HTML,

For example,

<div class="content">
                        <select name="group" id="group" style="width: 200px">
                                    <option value="1">Admin</option>
                                    <option value="2">Manager</option>
                                    <option value="3">Member</option>
                                    <option value="4">Guest</option>
                        </select>
            </div>

Then, create above Select Box, but using PHP as the following script,

            <div class="content">
            <?php
                        $group = array('1' => 'Admin', '2' => 'Manager', '3' => 'Member', '4' => 'Guest');
                        $xhtml = '';
           
                        if(!empty($group)) {
                                    $xhtml .= '<select name="group" id="group" style="width: 200px">';
                                    foreach ($group as $key => $value) {
                                                if($key == '3') {
                                                            $xhtml .= '<option value="'.$key.'"selected = "selected">'.$value.'</option>';           
                                                } else {
                                                            $xhtml .= '<option value="'.$key.'">'.$value.'</option>';
                                                }
                                    }
                                    $xhtml .= '</select>';
                        }
                        echo $xhtml;
            ?>                                          
            </div>

When creating a Select Box by using PHP means use a variable contains HTML, then echo HTML then.

You can using a function to create a Select Box for reusing then, for example,

<div class="content">
            <?php
                        $group = array('1' => 'Admin', '2' => 'Manager', '3' => 'Member', '4' => 'Guest');
                        $city  = array('ct' => 'Cần Thơ', 'hg' => 'Hậu Giang', 'bt' => 'Bến Tre');
                        function createSelectbox($name, $attributes, $array, $keySelect) {
                                    $xhtml = '';

                                    if(!empty($array)) {
                                                $xhtml .= '<select name="'.$name.'" id="'.$name.'" style="'.$attributes.'">';
                                                foreach ($array as $key => $value) {
                                                            if($key == $keySelect) {
                                                                        $xhtml .= '<option value="'.$key.'"selected = "selected">'.$value.'</option>';        
                                                            } else {
                                                                        $xhtml .= '<option value="'.$key.'">'.$value.'</option>';
                                                            }
                                                }
                                                $xhtml .= '</select>';
                                    }
                                    return $xhtml;
                        }
                        $groupSelect = createSelectbox('group', 'width: 200px', $group, 4);
                        $citySelect = createSelectbox('city', 'width: 300px', $city, 'hg');
                        echo $groupSelect;
                        echo '<br>';
                        echo $citySelect;
            ?>                                          
            </div>



</////07
-----------
Cập nhật [21/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 (x8) - PHP: sorting arrays

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

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

Bài trước: Học làm web (x4) - PHP: crash course 4
-----

1.2            Storing and retrieving data

Saving data for later (p54)


You can store data in two basic ways: in flat files (for example text file) or in a database.

Storing and retrieving Bob’s orders (p54)

Processing files (p55)


Writing data to a file requires three steps:

(1) Open the file. If the file doesn’t already exist, you need to create it

(2) Write data to the file

(3) Close the file

Similarly, reading data from file takes three steps:

(1) Open the file. If you cannot open the file (for example, if it doesn’t exist), you need to recognize this and exit gracefully

(2) Read data from the file

(3) Close the file

Opening a file (p55)


You use the fopen() function to open a file. You need to specify how you intend to use it. This is known as the file mode.

Choosing file modes

You need to make three choises when opening a file:

(1) You might want to open a file for reading only, for writing only, or for both reading and writing

(2) If writing to a file, you might want to overwrite any existing contents of a file or append new data to the end of the file. You also might like to terminate your program gracefully instead of overwriting a file if the file already exixts.

(3) If you are trying to write to a file on a system that differentiates between binary and text file, you might need to specify this fact.

Using fopen() to open a file (p56)

Assume that you want to write a customer order to Bob’s order file. You can open this file for writing with the following:

$fp = fopen(“$document_root/../orders/orders.txt”, ‘w’);
$document_root = $_SERVER['DOCUMENT_ROOT'];

Very few people use backslashes in paths within PHP because it means the code will work only in Windows environments. If you use forward slashes, you can often move your code between Windows and Unix machines without alteration.

If fopen() opens the file successfully, a resource that is effectively a handle or pointer to the file is returned and should be stored in a variable—in this case, $fp. You use this variable to access the file when you actually want to read from or write to it.

Opening files through FTP or HTTP (p58)

In addition to opening local files for reading and writing, you can open files via FTP, HTTP, and other protocols using fopen(). You can disable this capability by turning off the allow_url_fopen directive in the php.ini file. If you have trouble opening remote files with fopen(), check your php.ini file.

Addressing problems opening files (p58)

You could also choose to change ownership of the file to the web server user. Some people will choose to make the file world-writable as a shortcut here, but bear in mind that directories and files that anybody can write to are dangerous. In particular, directories that are accessible directly from the Web should not be writable. For this reason, our orders directory is outside the document tree.

If the call to fopen() fails, the function will return false. It will also cause PHP to emit a warning_level error (E_WARNING). You can deal with the error in a more user-friendly way by suppressing PHP’s error message and giving your own:

@$fp = fopen("$document_root/../orders/orders.txt", 'ab');
if (!$fp){
echo "<p><strong> Your order could not be processed at this time. "
.Please try again later.</strong></p></body></html>";
exit;
}

The @ symbol in front of the call to fopen() tells PHP to suppress any errors resulting from the function call. Usually, it’s a good idea to know when things go wrong, but in this case we’re going to deal with that problem elsewhere.

You can also write this line as follows:

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

Using this method tends to make it less obvious that you are using the error suppression operator, so it may make your code harder to debug.

Writing to a file (p61)


Writing to a file in PHP is relatively simple. You can use either of the functions fwrite() (file write) or fputs() (file put string); fputs() is an alias to fwrite(). You call fwrite() in the following way:

fwrite($fp, $outputstring);

This function call tells PHP to write the string stored in $outputstring to the file pointed to by $fp.
An alternative to fwrite() is the file_put_contents() function. It has the following prototype:

int file_put_contents ( string filename,
mixed data
[, int flags
[, resource context]])

This function writes the string contained in data to the file named in filename without any need for an fopen() (or fclose()) function call. This function is the half of a matched pair, the other half being file_get_contents(), which we discuss shortly.

Parameters for fwrite() (p62)

File formats (p62)

When you are creating a data file like the one in the example, the format in which you store the data is completely up to you. (However, if you are planning to use the data file in another application, you may have to follow that application’s rules.)

Now construct a string that represents one record in the data file. You can do this as follows:

$outputstring = $date.'\t'.$tireqty.' tires \t'.$oilqty.' oil\t'
.$sparkqty.' spark plugs\t\$'.$totalamount
.'\t'. $address.'\n';

order.txt:

18:55, 16th April 2013 4 tires 1 oil 6 spark plugs $477.4 22 Short St, Smalltown
18:56, 16th April 2013 1 tires 0 oil 0 spark plugs $110 33 Main Rd, Oldtown
18:57, 16th April 2013 0 tires 1 oil 4 spark plugs $28.6 127 Acacia St, Springfield

Closing a file (p63)


After you’ve finished using a file, you need to close it. You should do this by using the fclose() function as follows:

fclose($fp);

This function returns true if the file was successfully closed or false if it wasn’t. This process is much less likely to go wrong than opening a file in the first place, so in this case we’ve chosen not to test it.

Following is the final version of the Order Processing Script (processorder.php):

<?php
// create short variable names
$tireqty = $_POST['tireqty'];
$oilqty = $_POST['oilqty'];
$sparkqty = $_POST['sparkqty'];
$address = preg_replace('/\t|\R/',' ',$_POST['address']);
$document_root = $_SERVER['DOCUMENT_ROOT'];
$date = date('H:i, jS F Y');
?>
<!DOCTYPE html>
<html>
  <head>
    <title>Bob's Auto Parts - Order Results</title>
  </head>
  <body>
    <h1>Bob's Auto Parts</h1>
    <h2>Order Results</h2>
    <?php
      echo "<p>Order processed at ".$date."</p>";
      echo '<p>Your order is as follows: </p>';
     
      $totalqty = 0;
      $totalamount = 0.00;

      define('TIREPRICE', 100);
      define('OILPRICE', 10);
      define('SPARKPRICE', 4);
     
      $totalqty = $tireqty + $oilqty + $sparkqty;
      echo "<p>Items ordered: ".$totalqty."<br>";
     
      if ($totalqty == 0) {
        echo 'You did not order anything on the previous page! <br>';
      } else {
        if ($tireqty > 0) {
          echo htmlspecialchars($tireqty).' tires<br />';
        }
        if ($oilqty > 0) {
          echo htmlspecialchars($oilqty).' bottles of oil<br />';
        }
        if ($sparkqty > 0) {
           echo htmlspecialchars($sparkqty).' spark plugs<br />';
        }
      }
     
      $totalamount = $tireqty * TIREPRICE
                   + $oilqty * OILPRICE
                   + $sparkqty * SPARKPRICE;
    
      echo "Subtotal: $".number_format($totalamount,2)."<br>";

      $taxrate = 0.1; //local sales tax is 10%
      $totalamount = $totalamount * (1 + $taxrate);
      echo "Total including tax: $".number_format($totalamount,2)."</p>";
     
      echo '<p>Address to ship to is '.htmlspecialchars($address).'</p>';

      $outputstring = $date."\t".$tireqty." tires \t".$oilqty." oil \t".$sparkqty." spark plugs\t".$totalamount."\t".$address. "\n";

      //open file for appending
      @$fp = fopen("$document_root/../orders/orders.txt", 'ab');

      if (!$fp) {
        echo $document_root.'<br>';
        echo '<p><strong> Your order could not be processed at this time.
              Please try again later.</strong></p>';
              exit;
      }

      flock($fp, LOCK_EX);
      fwrite($fp, $outputstring, strlen($outputstring));
      flock($fp, LOCK_UN);
      fclose($fp);

      echo '<p>Order written.</p>';
    ?>
  </body>
</html>

</////05

-----------
Cập nhật [12/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 (x6) - PHP: storing and retrieving data (tt)