In this tutorial, we will demonstrate how to build a simple CRUD grid using PHP 8, MySQL, and Tailwind CSS.
We will need a database table to work on. Run the command below on MySQL console to create a database table "posts":
CREATE TABLE posts (
id INT(6) UNSIGNED AUTO_INCREMENT PRIMARY KEY,
title VARCHAR(30) NOT NULL,
content TEXT NOT NULL
)
Our plan is to work on the backend PHP code before creating any view pages.
Create a PHP file functions.php
.
Let's first create a function to connect to the database. This is a commonly shared function, that is used to create a PDO connection:
function connection($host, $database, $username, $password)
{
try {
$conn = new PDO("mysql:host=$host;dbname=$database", $username, $password);
// set the PDO error mode to exception
$conn->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
return $conn;
} catch (PDOException $e) {
echo "Connection failed: ".$e->getMessage();
}
}
To show all the posts, we create a function to list out all the posts records:
function listAll($connection)
{
$sql = "SELECT * FROM posts";
$statement = $connection->prepare($sql);
$statement->execute();
$statement->setFetchMode(PDO::FETCH_ASSOC);
$posts = $statement->fetchAll();
return $posts;
}
We create a function to create a post record:
function create($connection, $title, $content)
{
$sql = "INSERT INTO posts (title, content) VALUES (:title, :content)";
$stmt = $connection->prepare($sql);
$stmt->execute(['title' => $title, 'content' => $content]);
}
We create a function to update an existing post record:
function update($connection, $id, $title, $content)
{
$sql = "UPDATE posts SET title=:title, content=:content WHERE id=:id";
$stmt = $connection->prepare($sql);
$stmt->execute(['title' => $title, 'content' => $content, 'id' => $id]);
}
We create a function to delete an existing post record:
function delete($connection, $id)
{
$sql = "DELETE FROM posts WHERE id=:id";
$stmt = $connection->prepare($sql);
$stmt->execute(['id' => $id]);
}
Let's consolidate all the functions above, we will get a functions.php
with the content below:
function connection($host, $database, $username, $password)
{
try {
$conn = new PDO("mysql:host=$host;dbname=$database", $username, $password);
// set the PDO error mode to exception
$conn->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
return $conn;
} catch (PDOException $e) {
echo "Connection failed: ".$e->getMessage();
}
}
function listAll($connection)
{
$sql = "SELECT * FROM posts";
$statement = $connection->prepare($sql);
$statement->execute();
$statement->setFetchMode(PDO::FETCH_ASSOC);
$posts = $statement->fetchAll();
return $posts;
}
function create($connection, $title, $content)
{
$sql = "INSERT INTO posts (title, content) VALUES (:title, :content)";
$stmt = $connection->prepare($sql);
$stmt->execute(['title' => $title, 'content' => $content]);
}
function read($connection, $id)
{
$sql = "SELECT * FROM posts WHERE id = :id";
$stmt = $connection->prepare($sql);
$stmt->execute(['id' => $id]);
$stmt->setFetchMode(PDO::FETCH_ASSOC);
$post = $stmt->fetch();
return $post;
}
function update($connection, $id, $title, $content)
{
$sql = "UPDATE posts SET title=:title, content=:content WHERE id=:id";
$stmt = $connection->prepare($sql);
$stmt->execute(['title' => $title, 'content' => $content, 'id' => $id]);
}
function delete($connection, $id)
{
$sql = "DELETE FROM posts WHERE id=:id";
$stmt = $connection->prepare($sql);
$stmt->execute(['id' => $id]);
}
Time to start making the view page. The first page we are going to create is the page for creating a post.
We will be using Tailwind CSS for style.
Copy the content below to create.php
:
<?php
include 'functions.php';
if ($_POST) {
$connection = connection('localhost', 'crud', 'root', 'root');
create($connection, $_POST['title'], $_POST['content']);
$msg = 'Post created successfully';
}
?>
<!doctype html>
<html>
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<script src="https://cdn.tailwindcss.com"></script>
</head>
<body class="max-w-4xl mx-auto space-y-10 py-10">
<h1 class="text-3xl font-bold underline">Create </h1>
<?php if (isset($msg)): ?>
<div class="bg-green-100 border border-green-400 text-green-700 px-4 py-3 rounded relative" role="alert">
<strong class="font-bold">Success!</strong>
<span class="block sm:inline"><?php echo $msg; ?></span>
</div>
<?php endif; ?>
<form action="create.php" method="post">
<div class="mb-4">
<label class="block text-gray-700 text-sm font-bold mb-2" for="title">
Title
</label>
<input class="shadow appearance-none border rounded w-full py-2 px-3 text-gray-700 leading-tight focus:outline-none focus:shadow-outline"
id="title" name="title" type="text" placeholder="Title">
</div>
<div class="mb-6">
<label class="block text-gray-700 text-sm font-bold mb-2" for="content">
Content
</label>
<textarea
class="shadow appearance-none border rounded w-full py-2 px-3 text-gray-700 leading-tight focus:outline-none focus:shadow-outline"
id="content" name="content" type="text" placeholder="Content"></textarea>
</div>
<div class="flex items-center justify-between">
<button class="bg-blue-500 hover:bg-blue-700 text-white font-bold py-2 px-4 rounded focus:outline-none focus:shadow-outline"
type="submit">
Submit
</button>
<a href="index.php"
class="bg-gray-500 hover:bg-gray-700 text-white font-bold py-2 px-4 rounded focus:outline-none focus:shadow-outline"
type="submit">
Cancel
</a>
</div>
</form>
</body>
</html>
Make sure you change the credentials according to when calling $connection = connection('localhost', 'crud', 'root', 'root');
method on top of the page.
Start the webserver php -S localhost:8888
, and navigate to URL http://localhost:8888/create.php
on your browser. You should be able to see a good-looking page for post creation:
Now we have successfully implemented the page to create a post, time to list out the posts we have created.
Copy the content below to index.php
:
<?php
include 'functions.php';
$connection = connection('localhost', 'crud', 'root', 'root');
$posts = listAll($connection);
?>
<!doctype html>
<html>
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<script src="https://cdn.tailwindcss.com"></script>
</head>
<body class="max-w-4xl mx-auto space-y-10 py-10">
<div class="flex items-center justify-between">
<h1 class="text-3xl font-bold underline">List </h1>
<a href="create.php"
class="bg-blue-500 hover:bg-blue-700 text-white font-bold py-2 px-4 rounded focus:outline-none focus:shadow-outline">Create</a>
</div>
<table class="table-auto w-full">
<thead>
<tr>
<th class="px-4 py-2 text-left">Title</th>
<th class="px-4 py-2 text-left">Content</th>
<th class="px-4 py-2 text-left">Actions</th>
</tr>
</thead>
<tbody>
<?php foreach ($posts as $post): ?>
<tr>
<td class="border p-4"><?php echo $post['title']; ?></td>
<td class="border p-4"><?php echo $post['content']; ?></td>
<td class="border p-4">
<a href="update.php?id=<?php echo $post['id']; ?>"
class="bg-blue-500 hover:bg-blue-700 text-white font-bold py-2 px-4 rounded focus:outline-none focus:shadow-outline">Edit</a>
<a href="delete.php?id=<?php echo $post['id']; ?>"
onclick="return confirm('Are you sure to delete?');"
class="bg-red-500 hover:bg-red-700 text-white font-bold py-2 px-4 rounded focus:outline-none focus:shadow-outline">Delete</a>
</td>
</tr>
<?php endforeach; ?>
</tbody>
</table>
</body>
</html>
Again, make sure you update the credentials on top of the page $connection = connection('localhost', 'crud', 'root', 'root');
.
Now navigate to http://localhost:8888/index.php
, you should be able to see a listing page:
If you click the Edit
button on the index page, it will give you a 404 page. We are going to fix that on this step.
Copy the content below to update.php
:
<?php
include 'functions.php';
$connection = connection('localhost', 'crud', 'root', 'root');
if ($_POST) {
update($connection, $_GET['id'], $_POST['title'], $_POST['content']);
$msg = 'Post updated successfully';
}
$post = read($connection, $_GET['id']);
?>
<!doctype html>
<html>
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<script src="https://cdn.tailwindcss.com"></script>
</head>
<body class="max-w-4xl mx-auto space-y-10 py-10">
<h1 class="text-3xl font-bold underline">Update </h1>
<?php if (isset($msg)): ?>
<div class="bg-green-100 border border-green-400 text-green-700 px-4 py-3 rounded relative" role="alert">
<strong class="font-bold">Success!</strong>
<span class="block sm:inline"><?php echo $msg; ?></span>
</div>
<?php endif; ?>
<!-- a update form to update a post -->
<form action="update.php?id=<?= $_GET['id'] ?>" method="post">
<div class="mb-4">
<label class="block text-gray-700 text-sm font-bold mb-2" for="title">
Title
</label>
<input class="shadow appearance-none border rounded w-full py-2 px-3 text-gray-700 leading-tight focus:outline-none focus:shadow-outline"
value="<?= $post['title'] ?>"
id="title" name="title" type="text" placeholder="Title">
</div>
<div class="mb-6">
<label class="block text-gray-700 text-sm font-bold mb-2" for="content">
Content
</label>
<textarea
class="shadow appearance-none border rounded w-full py-2 px-3 text-gray-700 leading-tight focus:outline-none focus:shadow-outline"
id="content" name="content" type="text" placeholder="Content"><?= $post['content'] ?></textarea>
</div>
<div class="flex items-center justify-between">
<button class="bg-blue-500 hover:bg-blue-700 text-white font-bold py-2 px-4 rounded focus:outline-none focus:shadow-outline"
type="submit">
Submit
</button>
<a href="index.php"
class="bg-gray-500 hover:bg-gray-700 text-white font-bold py-2 px-4 rounded focus:outline-none focus:shadow-outline"
type="submit">
Cancel
</a>
</div>
</form>
</body>
</html>
Update the credentials on $connection = connection('localhost', 'crud', 'root', 'root');
. Now the Update
page should work too:
The last piece for us to fix is the Delete
button.
Copy the content below to delete.php
:
<?php
include 'functions.php';
if ($_GET['id']) {
$connection = connection('localhost', 'crud', 'root', 'root');
delete($connection, $_GET['id']);
header('Location: index.php');
}
?>
Update the credentials as usual. Now the Delete
button on the listing page should be working too.
You have completed a very simple CRUD grid using PHP 8 and Tailwind CSS.