Using PHP and MySQL to build web pages
Before we begin, let’s allow the user george
to connect to MySQL/MariaDB from any host, including the server that hosts php and the web server.
We will use %
to allow connection from all hosts:
MariaDB [(none)]> GRANT ALL PRIVILEGES ON `publications`.* TO "george"@"%";
Query OK, 0 rows affected (0.010 sec)
We will be creating the login.php
file which we will be using in other php
files.
This code will help us connect to the MySQL database with the user and password, and the publications
database will be selected.
This code is visible and executed only by the server, it is not visible by the web browser.
<?php // login.php
$host = 'mariadb'; // Change as necessary
$data = 'publications'; // Change as necessary
$user = 'george'; // Change as necessary
$pass = 'password'; // Change as necessary
$chrs = 'utf8mb4';
$attr = "mysql:host=$host;dbname=$data;charset=$chrs";
$opts =
[
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,
PDO::ATTR_EMULATE_PREPARES => false,
];
?>
To connect to MySQL, we create a new PDO connection.
An error message will be displayed if the connection is not successful.
<?php // query.php
require_once 'login.php';
try
{
$pdo = new PDO($attr, $user, $pass, $opts);
}
catch (PDOException $e)
{
throw new PDOException($e->getMessage(), (int)$e->getCode());
}
?>
In the next step we will be doing an SQL query and placing its output in the $result
object.
<?php
$query = "SELECT * FROM classics";
$result = $pdo->query($query);
?>
The final step will be displaying the results in a web page. Here is the final code:
<?php // query.php
require_once 'login.php';
try
{
$pdo = new PDO($attr, $user, $pass, $opts);
}
catch (PDOException $e)
{
throw new PDOException($e->getMessage(), (int)$e->getCode());
}
$query = "SELECT * FROM classics";
$result = $pdo->query($query);
while ($row = $result->fetch())
{
echo 'Author: ' . htmlspecialchars($row['author']) . "<br>";
echo 'Title: ' . htmlspecialchars($row['title']) . "<br>";
echo 'Category: ' . htmlspecialchars($row['category']) . "<br>";
echo 'Year: ' . htmlspecialchars($row['year']) . "<br>";
echo 'ISBN: ' . htmlspecialchars($row['isbn']) . "<br><br>";
}
?>
The resulting html
source of web page (<br>
tags are for adding new lines):
Author: Charles Dickens<br>
Title: The Old Curiosity Shop<br>
Category: Classic Fiction<br>
Year: 1841<br>
ISBN: 9780099533474<br>
<br>Author: William Shakespeare<br>
Title: Romeo and Juliet<br>
Category: Play<br>Year: 1594<br>
ISBN: 9780192814968<br>
This is what the web browser will render:
Author: Charles Dickens
Title: The Old Curiosity Shop
Category: Classic Fiction
Year: 1841
ISBN: 9780099533474
Author: William Shakespeare
Title: Romeo and Juliet
Category: Play
Year: 1594
ISBN: 9780192814968
Let’s look at a more complex example, where we can either add a record to the classics
writers database, or delete existing ones.
We first connect via PDO to the database.
We define a function to validate ISBN numbers - 10 or 13 digits - called validate_isbn
.
For this, we use the PHP function preg_match
to do a regular expression search for ISBN numbers, explained below:
Regular expression - ^\d{10}$|^\d{13}$ 1st Alternative ^\d{10}$ ^ asserts *position* at start of a line \d matches a digit (equivalent to [0-9]) {10} matches the previous token exactly 10 times $ asserts position at the end of a line 2nd Alternative ^\d{13}$ ^ asserts *position* at start of a line \d matches a digit (equivalent to [0-9]) {13} matches the previous token exactly 13 times $ asserts position at the end of a line
.
<?php // sqltest.php
require_once 'login.php';
try {
// Establish a database connection using PDO
$pdo = new PDO($attr, $user, $pass, $opts);
} catch (PDOException $e) {
// Generic error handling
echo "Database connection error.";
exit;
}
// Function to validate ISBN
function validate_isbn($isbn) {
return preg_match('/^\d{10}$|^\d{13}$/', $isbn); // Match 10 or 13 digits
}
// Function to check if any field is empty
function are_fields_empty(...$fields) {
foreach ($fields as $field) {
if (empty(trim($field))) {
return true; // Return true if any field is empty
}
}
return false; // Return false if all fields are filled
}
// Function to validate year
function validate_year($year) {
return preg_match('/^\d{4}$/', $year) && $year > 0; // Checks if year is a 4-digit positive integer
}
// Initialize an array to hold error messages
$errors = [];
// Handle deletion of records
if (isset($_POST['delete']) && isset($_POST['isbn'])) {
$isbn = get_post($pdo, 'isbn');
// Use prepared statements to execute the deletion
$stmt = $pdo->prepare("DELETE FROM classics WHERE isbn = :isbn");
$stmt->execute(['isbn' => $isbn]);
}
// Handle insertion of records
if ($_SERVER["REQUEST_METHOD"] == "POST") {
$author = get_post($pdo, 'author');
$title = get_post($pdo, 'title');
$category = get_post($pdo, 'category');
$year = get_post($pdo, 'year');
$isbn = get_post($pdo, 'isbn');
// Validate fields
if (are_fields_empty($author, $title, $category, $year, $isbn)) {
$errors[] = "All fields are required!";
}
if (!validate_isbn($isbn)) {
$errors[] = "ISBN must be either 10 or 13 digits!";
}
if (!validate_year($year)) {
$errors[] = "Year must be a valid 4-digit integer!";
}
// Check for duplicate ISBN
if (empty($errors)) {
$stmt = $pdo->prepare("SELECT COUNT(*) FROM classics WHERE isbn = :isbn");
$stmt->execute(['isbn' => $isbn]);
$exists = $stmt->fetchColumn();
if ($exists) {
$errors[] = "This ISBN already exists in the database!";
}
}
// If no errors, insert the record
if (empty($errors)) {
// Use prepared statements for insertion
$stmt = $pdo->prepare("INSERT INTO classics (author, title, category, year, isbn) VALUES (:author, :title, :category, :year, :isbn)");
$stmt->execute(['author' => $author, 'title' => $title, 'category' => $category, 'year' => $year, 'isbn' => $isbn]);
}
}
// Display error messages if any
if (!empty($errors)) {
echo "<section style='color:red;'>";
foreach ($errors as $error) {
echo "<p>$error</p>";
}
echo "</section>";
}
// Pre-fill form values to retain user input
$form_author = $_POST['author'] ?? '';
$form_title = $_POST['title'] ?? '';
$form_category = $_POST['category'] ?? '';
$form_year = $_POST['year'] ?? '';
$form_isbn = $_POST['isbn'] ?? '';
echo <<<_END
<form action="sqltest.php" method="post"><pre>
Author <input type="text" name="author" value="$form_author">
Title <input type="text" name="title" value="$form_title">
Category <input type="text" name="category" value="$form_category">
Year <input type="text" name="year" value="$form_year">
ISBN <input type="text" name="isbn" value="$form_isbn">
<input type="submit" value="ADD RECORD">
</pre></form>
_END;
// Fetch and display records from the database
$query = "SELECT * FROM classics";
$result = $pdo->query($query);
while ($row = $result->fetch()) {
$r0 = htmlspecialchars($row['author']);
$r1 = htmlspecialchars($row['title']);
$r2 = htmlspecialchars($row['category']);
$r3 = htmlspecialchars($row['year']);
$r4 = htmlspecialchars($row['isbn']);
echo <<<_END
<pre>
Author: $r0
Title: $r1
Category: $r2
Year: $r3
ISBN: $r4
</pre>
<form action='sqltest.php' method='post'>
<input type='hidden' name='delete' value='yes'>
<input type='hidden' name='isbn' value='$r4'>
<input type='submit' value='DELETE RECORD'></form>
_END;
}
function get_post($pdo, $var) {
return htmlspecialchars(trim($_POST[$var] ?? ''));
}
?>
.