Almost every web application is built on four operations. They have a name: CRUD.
| Letter | Operation | SQL | Typical page |
|---|---|---|---|
| C | Create | INSERT | “Add product” form |
| R | Read | SELECT | Product list and product page |
| U | Update | UPDATE | “Edit product” form |
| D | Delete | DELETE | Delete button |
A blog (posts), a shop (products), a task list (tasks), a contact manager: all are CRUD with different data.
CRUD and HTTP
| Operation | Request |
|---|---|
| List / show | GET /products, GET /products?id=3 |
| Show the create form | GET /product-new.php |
| Create | POST /product-new.php |
| Show the edit form | GET /product-edit.php?id=3 |
| Update | POST /product-edit.php |
| Delete | POST /product-delete.php |
Reading uses GET. Anything that changes data uses POST (see POST Method).
The plan for this chapter
We will build a small product manager, one operation at a time, and put it together in the last lesson.
The table (from Creating a Database and Table):
CREATE TABLE products (
id INT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
name VARCHAR(150) NOT NULL,
price DECIMAL(10,2) NOT NULL,
stock INT NOT NULL DEFAULT 0,
category VARCHAR(50) NOT NULL DEFAULT 'general'
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
The files:
product-manager/
├── db.php the PDO connection
├── ProductRepository.php all SQL lives here
├── index.php list, search, filter, sort, pagination
├── product-form.php create and edit form
├── product-delete.php deletes (POST only)
└── layout/header.php, footer.php
Why a repository?
Putting all SQL for products in one class (a repository) keeps your pages clean and your queries in one place. A page calls $repo->find(3) and does not care about SQL.
<?php
final class ProductRepository
{
public function __construct(private PDO $pdo) {}
public function find(int $id): ?array
{
$statement = $this->pdo->prepare("SELECT id, name, price, stock, category FROM products WHERE id = :id");
$statement->execute(["id" => $id]);
return $statement->fetch() ?: null;
}
}
$repo = new ProductRepository(require __DIR__ . "/db.php");
echo $repo->find(1)["name"];
Notebook
The safety rules for every page
- Validate every input before it reaches the database.
- Use prepared statements for every value.
- Escape every value you print into HTML.
- Use POST for changes, and a CSRF token (see CSRF).
- Check that the user is allowed to do the operation.
- After a successful change, redirect (Post/Redirect/Get).
- Show friendly errors. Log the technical details.