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)