Storing data with PHP

I. File Handling

Checking Whether a File Exists

Windows and macOS filenames are not case-sensitive, but Linux and Unix filenames are.

PHP

<?php
if (file_exists("page.php")) echo "File exists";
?>

Result

Creating a File

  1. Always start by opening the file. You do this through a call to fopen.
  2. Then you can call other functions; we write to the file (fwrite), read from an existing file (fread or fgets) and do other things.
  3. Finish by closing the file (fclose).
The $My_File variable is a number PHP uses to refer to internal information about the file.
Upon failure, FALSE will be returned by fopen. To capture and respond to the failure: it calls the die function to end the program and give the user an error message.
The second parameter to the fopen call: the character w, which tells the function to open the file for writing. The function creates the file if it doesn't already exist.
If the file already exists, the w mode parameter causes the fopen call to delete the old contents (even if you don't write anything new!).

PHP

<?php
$My_File = fopen("test.txt", 'w') or die("Failed to create file");
// some code to be executed...
fclose($My_File);
?>

Result

The file test.txt should now be residing in the same folder in which you saved the php program.
Mode Action Description
'r' Read from file's beginning Open for reading only; place the file pointer at the beginning of the file. Return FALSE if the file doesn't already exist.
'r+' Read from file's beginning and allow writing Open for reading and writing; place the file pointer at the beginning of the file. Return FALSE if the file doesn't already exist.
'w' Write from file's beginning and truncate file Open for writing only; place the file pointer at the beginning of the file and truncate the file to zero length. If the file doesn't exist, attempt to create it.
'w+' Write from file's beginning, truncate file, and allow reading Open for reading and writing; place the file pointer at the beginning of the file and truncate the file to zero length. If the file doesn't exist, attempt to create it.
'a' Append to file's end Open for writing only; place the file pointer at the end of the file. If the file doesn't exist, attempt to create it.
'a+' Append to file's end and allow reading Open for reading and writing; place the file pointer at the end of the file. If the file doesn't exist, attempt to create it.

Reading a File

  • To grabs a whole line from the file use fgets.
  • You can retrieve multiple lines or portions of lines through the fread function.

PHP

<?php
$My_File = fopen("test.txt", 'r') or die("Failed to create file");
$line = fgets($My_File);
$text = fread($My_File, 3); // 3 is the number of characters to read.
fclose($My_File);
echo '$line ' . $line . ' <br>';
echo '$text ' . $text . ' <br>';
?>

Result

It will print the first line of the file and the first 3 characters of the second line.

Copying a File

  • Use the copy function to copy a file.
  • It takes two parameters: the name of the file to copy and the name of the new file.
  • It returns TRUE if the copy succeeds and FALSE if it fails.

PHP

<?php
copy('test.txt', 'test2.txt') or die("Could not copy file");
echo "File successfully copied to 'test2.txt'";
?>

Result

Moving a File

  • Use the rename function to move a file.
  • It takes two parameters: the name of the file to move and the new name of the file.
  • It returns TRUE if the move succeeds and FALSE if it fails.

PHP

<?php
rename('test.txt', 'Another_Location/test.txt') or die("Could not move file");

?>

Result

Deleting a File

  • Use the unlink function to delete a file.
  • It takes one parameter: the name of the file to delete.
  • It returns TRUE if the delete succeeds and FALSE if it fails.

PHP

<?php
unlink('test2.txt') or die("Could not delete file");

?>

Result

Updating a File

  • The file pointer is the position within a file at which the next file access will take place, whether it's a read or a write. It is not the same as the file handle which contains details about the file being accessed.
  • 'r+', which puts the file pointer right at the start.
  • The fseek function is called to move the file pointer right to the file end.
  • The fseek function was passed two other parameters, 0 and SEEK_END. SEEK_END tells the function to move the file pointer to the end of the file, and 0 tells it how many positions it should then be moved backward from that point.
  • There are two other seek options available to the fseek function: SEEK_SET and SEEK_CUR.
    1. The SEEK_SET option tells the function to set the file pointer to the exact position given by the preceding parameter.
    2. The SEEK_CUR sets the file pointer to the current position plus the value of the given offset.

PHP

<?php
$My_File = fopen("test.txt", 'r+') or die("Failed to open file");
$text = "This is some text that we will write to the file";
fseek($My_File, -20, SEEK_END);
fwrite($My_File, "\n$text") or die("Could not write to file");
fseek($My_File, 30, SEEK_SET);
fwrite($My_File, "This text should be written at the position 30 ") or die("Could not write to file");
fseek($My_File, 5, SEEK_CUR);
fwrite($My_File, "This text should be written at the position 30 + 5 ") or die("Could not write to file");
fclose($My_File);
?>

Result

  • Use the file_put_contents function to update a file.
  • It takes two parameters: the name of the file to update and the new content of the file.
  • It returns the number of bytes written to the file if the update succeeds and FALSE if it fails.

Locking Files for Multiple Acces

  • The flock function. This function queues up all other requests to access a file until your program releases the lock.
  • The first call to flock sets an exclusive file lock on the file referred to by $My_File using the LOCK_EX parameter.
  • After that, you release the lock by using the LOCK_UN parameter.
  • The call to request an exclusive lock is nested as part of an if statement. This is because flock is not supported on all systems

PHP

<?php
$My_File = fopen("test.txt", 'r+') or die("Failed to open file");
$text = "This is a test that will be written at the end. \n";
if (flock($My_File, LOCK_EX)) {
fseek($My_File, 0, SEEK_END);
fwrite($My_File, "$text") or die("Could not write to file");
flock($My_File, LOCK_UN);
}
fclose($My_File);
echo "File 'test.txt' successfully updated";
?>

Result

Reading an Entire File

  • Use the file_get_contents function to read an entire file.
  • It takes one parameter: the name of the file to read.
  • It returns the contents of the file if the read succeeds and FALSE if it fails.

PHP

<?php
echo file_get_contents("https://www.ensia.edu.dz/");
?>

Result

Uploading Files

  • Use the move_uploaded_file function to upload a file.
  • It takes two parameters: the name of the file to upload and the name of the new file.
  • It returns TRUE if the upload succeeds and FALSE if it fails.
  • All uploaded files are placed into the associative system array $_FILES.

PHP

<form method='post' action='index.php' enctype='multipart/form-data'>
<label for="File_Input">Select File: </label>
<input type='file' name='filename' size='10' id="File_Input">
<input type='submit' value='Upload'>
</form>
<?php
if ($_FILES) { // Checks if empty
$name = $_FILES['filename']['name'];
move_uploaded_file($_FILES['filename']['tmp_name'], $name);
echo "Uploaded image '$name'<br><img src='$name'> <br>";
foreach ($_FILES as $key => $value) {
echo " $key : <br>";
foreach ($value as $key2 => $value2) {
echo " $key2 : $value2 <br>";
} } }
?>

Result

Array element Content
$_FILES['file']['name'] The name of the uploaded file
$_FILES['file']['type'] The content type of the file
$_FILES['file']['size'] The file's size in bytes
$_FILES['file']['tmp_name'] The name of the temporary file stored on the server
$_FILES['file']['error'] The error code resulting from the file upload

II. MySQLi

How Web Database Architectures Work

PHP_MySQL
  1. A user's web browser issues an HTTP request for a particular web page (requested a search using an HTML form). The search results page is called action.php.
  2. The web server receives the request for results.php, retrieves the file, and passes it to the PHP engine for processing.
  3. The PHP engine begins parsing the script. Inside the script is a command to connect to the database and execute a query. PHP opens a connection to the MySQL server and sends on the appropriate query.
  4. The MySQL server receives the database query, processes it, and sends the results back to the PHP engine.
  5. The PHP engine finishes running the script. This usually involves formatting the query results nicely in HTML. It then returns the resulting HTML to the web server.
  6. The web server passes the HTML back to the browser.

Querying a Database from the Web

In any script used to access a database from the Web, you follow some basic steps:
  1. Check and filter data coming from the user.
  2. Set up a connection to the appropriate database.
  3. Query the database.
  4. Retrieve the results.
  5. Present the results back to the user.

Checking and Filtering Input Data

We begin the script by stripping any whitespace that the user might have inadvertently entered at the beginning or end of his input field. You can do this by applying the function trim():

$My_Variable=trim($_POST['Input_Name']);

The next step is to verify that the user has entered somthing. Note that we check whether the user entered a search term after trimming whitespace.

Setting Up a Connection

The basic PHP library for connecting to MySQL is called mysqli. The i stands for improved, as there was an older library called mysql. When using the mysqli library in PHP, you can use either an object-oriented or procedural syntax.
You use the following line in the script to connect to the MySQL server:

@$db = new mysqli('Server_name', 'User_Name', 'Password', 'Database_Name');

This line instantiates the mysqli class and creates a connection to host Server_name with username User_Name, and password Password. The connection is set up to use the database called Database_Name.
To connect in a procedural fashion, you can use:

@$db = mysqli_connect('Server_name', 'User_Name', 'Password', 'Database_Name');

This function returns a resource rather than an object. This resource represents the connection to the database, and if you are using the procedural approach, you will need to pass this resource in to all the other mysqli functions. This is similar to the way the file-handling functions, such as fopen(), work.
The procedural version function names start with mysqli_.

Object-oriented

<?php
@$My_Connection = new mysqli('localhost', 'root', '', 'my_db');
if (mysqli_connect_errno()) {
echo 'Error: Could not connect to database. Please try again later.';
exit;
} else {
echo 'Connected to database. <br />';
}
?>

Procedural

<?php
@$My_Connection = mysqli_connect('localhost', 'root', '', 'my_db', 3366);
if (mysqli_connect_errno()) {
echo 'Error: Could not connect to database. Please try again later.';
exit;
} else {
echo 'Connected to database. Procedural <br />';
}
?>
  • The result of your attempt at connection is worth checking because none of the rest of code will work without a valid database connection.
  • The mysqli_connect_errno() function returns an error number on error, or zero on success (This code is the same for the object-oriented and procedural versions).
  • Note that when you connect to the database, you begin the line of code with the error suppression operator, @ to handle any errors (This could also be done with exceptions).
  • Bear in mind that there is a limit to the number of MySQL connections that can exist at the same time. The MySQL parameter max_connections determines what this limit is. The purpose of this parameter and the related Apache parameter MaxClients is to tell the server to reject new connection requests instead of allowing machine resources to be completely used up at busy times or when software has crashed.
  • You can alter both of these parameters from their default values by editing the configuration files. To set MaxClients in Apache, edit the httpd.conf file on your system. To set max_connections for MySQL, edit the file my.conf.

Choosing a Database to Use

If you want to change the default database, you can do so with the mysqli_select_db() function.
The procedural version begins with mysqli_ and requires the extra database handle parameter.

Object-oriented

<?php
$My_Connection->select_db('my_db2');
?>

Procedural

<?php
mysqli_select_db($My_Connection, 'my_db2');
?>

Querying the Database

To actually perform the query, you can use the mysqli_query() function. Before doing this, however, it's a good idea to set up the query you want to run:

$query = "SELECT * FROM user WHERE user.User_ID<=?";

The reason we have a question mark in the query is that we're going to use a type of query known as a prepared statement. The question mark is a placeholder. This tells MySQL, "whatever we replace the question mark with should be treated as data only, and not code."
Placeholders can only be used for data, and not for column, table, or database names.
Remember that the query you send to MySQL does not need a semicolon at the end of it, unlike a query you type into the MySQL monitor.
You should not put any quotation marks or other delimiters around these question marks.

Using Prepared Statements

The mysqli library supports the use of prepared statements. These are useful for speeding up execution when you are performing large numbers of the same query with different data.
The basic concept of a prepared statement is that you send a template of the query you want to execute to MySQL and then send the data separately.
The function $db->prepare(), which is called mysqli_stmt_prepare() in the procedural version. This line constructs a statement object or resource that you will then use to do the actual processing.
The statement object has a method called bind_param(). (In the procedural version, it is called mysqli_stmt_bind_param()). The purpose of bind_param() is to tell PHP which variables should be substituted for the question marks. The first parameter is a format string.
Other possible characters in the format string are i for integer and b for blob. After this parameter, you should list the same number of variables as you have question marks in your statement. They will be substituted in this order.
The call to $stmt->execute() (mysqli_stmt_execute() in the procedural version) actually runs the query.

Object-oriented

<?php
$Number = 10;
$stmt = $My_Connection->prepare($query);
$stmt->bind_param('i', $Number);
$stmt->execute();
?>

Procedural

<?php
$Number = 10;
$stmt = mysqli_stmt_init($My_Connection);
mysqli_stmt_prepare($stmt, $query);
mysqli_stmt_bind_param($stmt, 'i', $Number);
mysqli_stmt_execute($stmt);
?>

Retrieving the Query Results

A large variety of functions is available to break the results out in different ways.
As well as binding parameters, you can bind results. For SELECT-type queries, you can use $stmt->bind_result() (or mysqli_stmt_bind_result()) to provide a list of variables that you would like the result columns to be filled into. Each time you call $stmt->fetch() (or mysqli_stmt_fetch()), column values from the next row in the resultset are filled into these bound variables.

Object-oriented

<?php
$stmt->store_result();
echo "Number of rows found: " . $stmt->num_rows . "<br />";
$stmt->bind_result($User_ID, $Name, $Birthdate, $Address);
while ($stmt->fetch()) {
echo "<p><strong>User_ID: " . $User_ID . "</strong>";
echo "<br />Name: " . $Name;
echo "<br />Birthdate: " . $Birthdate;
echo "<br />Address: " . $Address;
echo "<br />-------------------------------------------</p>";
}
?>

Procedural

<?php
mysqli_stmt_bind_result($stmt, $User_ID, $Name, $Birthdate, $Address);
while (mysqli_stmt_fetch($stmt)) {
echo "<p><strong>User_ID: " . $User_ID . "</strong>";
echo "<br />Name: " . $Name;
echo "<br />Birthdate: " . $Birthdate;
echo "<br />Address: " . $Address;
echo "<br />-------------------------------------------</p>";
}
?>
If we'd like to get a count of the number of rows returned, we first tell PHP to retrieve and buffer all of the rows returned from the query: $stmt->store_result(); When you use the object-oriented approach, the number of rows returned is stored in the num_rows member of the result object.
When you use a procedural approach, the function mysqli_num_rows() gives you the number of rows returned by the query. You should pass it the result identifier.

Object-oriented

<?php
$stmt->store_result();
echo "Number of rows found: " . $stmt->num_rows . "<br />";
?>

Procedural

<?php
$result = mysqli_stmt_get_result($stmt);
$num_results = mysqli_num_rows($result);
echo 'Number of records found: ' . $num_results . '<br />';
?>
There are other approaches to fetching data from a query result other than using mysqli_stmt_fetch(). To use these, first we must extract a result set resource from the statement. You can do this using the mysqli_stmt_get_result() function.
This function returns an instance of the mysqli_result object, which itself has a number of useful functions for extracting the data. Probably the most useful are:
  • mysqli_fetch_array() (and related mysqli_fetch_assoc()), which returns the next row from the result set as an array. The mysqli_fetch_assoc() version uses the column names as keys, although you can also get this behavior from mysqli_fetch _array(). The mysqli_fetch_array() function takes a second parameter for the type of array to return. Passing MYSQLI_ASSOC will get you the column names as keys, passing MYSQLI_NUM will result in numbered keys, and MYSQLI_BOTH will give you an array containing two sets of the data, one with column names as keys and one with numerical keys.
  • mysqli_fetch_all() returns all of the rows returned by the query as an array of arrays where each of the inner arrays is one of the rows returned.
  • mysqli_fetch_object() returns the next row from the result set as an object, where each value is stored in an attribute carrying the name of the column.

Object-oriented

<?php
//After execute
$result = $stmt->get_result();
while ($row = mysqli_fetch_assoc($result)) {
foreach ($row as $key => $value) {
echo $key . ' : ' . $value . '<br />';
}
echo '---------------------------------<br />';
}
?>

Procedural

<?php
while ($row = mysqli_fetch_assoc($result)) {
foreach ($row as $key => $value) {
echo $key . ' : ' . $value . '<br />';
}
echo '---------------------------------<br />';
}
?>

Inserting data into the Database

Inserting new items into the database is remarkably similar to getting items out of the database.

HTML

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<form action="index.php" method="post">
<label for="Name">Name</label>
<input type="text" name="Name" id="Name"> <br>
<label for="Birthdate">Birthdate</label>
<input type="date" name="Birthdate" id="Birthdate"> <br>
<label for="Address">Address</label>
<input type="text" name="Address" id="Address"> <br>
<input type="submit" value="submit" name="submit">
</form>
</body>
</html>

PHP

<?php
if (!isset($_POST['Name']) || !isset($_POST['Birthdate']) || !isset($_POST['Address'])) {
echo '<h1>Please fill all the fields</h1>';
exit();
}
$Name = $_POST['Name'];
$Birthdate = $_POST['Birthdate'];
$Address = $_POST['Address'];
@$My_Connection = new mysqli('localhost', 'root', '', 'my_db', 3366);
$query = "INSERT INTO `user` ( `Name`, `BirthDate`, `Address`) VALUES (?, ?,?)";
$stmt = $My_Connection->prepare($query);
$stmt->bind_param('sss', $Name, $Birthdate, $Address);
$stmt->execute();
?>

Disconnecting from the Database

You can free your result set by calling either

$result->free();

or

mysqli_free_result($result);

You can then use

$db->close();

or

mysqli_close($db);

to close a database connection. Using this command isn't strictly necessary because the
connection will be closed when a script finishes execution anyway.

III. PDO

Setting Up a Connection

  • When you create a new PDO object, you pass it the connection details for the database you want to connect to.
  • The first parameter is a string containing the database type, the host name, and the database name (dsn or Data Source Name).
  • The second parameter is the username for the database.
  • The third parameter is the password for the database.
  • The fourth parameter is an array of options. You can use this to set the error mode and other options.

PHP

<?php
try {
$Connection = new PDO("mysql:host=localhost;dbname=my_db;port=3366", "root", "");
echo "Connected successfully";
} catch (PDOException $e) {
throw new PDOException($e->getMessage(), (int)$e->getCode());
}
?>

Result

Connected successfully OR

Any error that may occur while connecting to the database.

Querying the Database

  • Use the query function to query the database.
  • It takes one parameter: the query to run.
  • It returns a PDOStatement object if the query succeeds and FALSE if it fails.
  • The query function prepares and executes an SQL statement without placeholders
  • Once you have an object returned in $result, you can use it to extract the data you want, one item at a time, using the fetch method of the object. The fetch method can return data in various styles, including the following:
    • PDO::FETCH_ASSOC Returns the next row as an array indexed by column name.
    • PDO::FETCH_BOTH (default) Returns the next row as an array indexed by both column name and number.
    • PDO::FETCH_LAZY Returns the next row as an anonymous object with names as properties.
    • PDO::FETCH_OBJ Returns the next row as an anonymous object with column name as properties.
    • PDO::FETCH_NUM Returns an array indexed by column number.

PHP

<?php
$query = "SELECT * FROM User where User_Id<=10";
$result = $Connection->query($query);
while ($row = $result->fetch()) {
echo 'Name: ' . htmlspecialchars($row['Name']) . "<br>";
echo 'Birthdate: ' . htmlspecialchars($row['BirthDate']) . "<br>";
echo 'Address: ' . htmlspecialchars($row['Address']) . "<br>";
echo "---------------------------------------------<br />";
}
?>

Result

Using Prepared Statements

The prepare function is used to prepare a statement for execution and returns a statement object.
It takes one parameter: the query to prepare.
The bindParam function is used to bind a parameter to the specified variable name.
The first argument to bindParam is a number representing the position in the query string of the value to insert (in other words, which question mark placeholder is being referred to). This is followed by the variable that will supply the data for that placeholder, and then the type of data the variable must be, and, if a string, another value follows stating its maximum length.
At this point, PHP has everything it needs to execute the prepared statement, so you can issue the following command, which calls the execute method of the $stmt object created earlier, passing the values to be inserted in the form of an array.

PHP

<?php
$Number = 10;
$query = "SELECT * FROM User where User_Id <=?";
$stmt=$Connection->prepare($query);
$stmt->bindParam(1, $Number, PDO::PARAM_INT);
$stmt->execute([$Number]);
echo "Number of rows: " . $stmt->rowCount() . "<br>";
while ($My_Results = $stmt->fetch(PDO::FETCH_ASSOC)) {
echo 'Name: ' . htmlspecialchars($My_Results['Name']) . "<br>";
echo 'Birthdate: ' . htmlspecialchars($My_Results['BirthDate']) . "<br>";
echo 'Address: ' . htmlspecialchars($My_Results['Address']) . "<br>";
echo "---------------------------------------------<br />";
}
?>

Result