A PHP CRUD endpoint should validate input, use PDO prepared statements, enforce authorization, and return a deliberate response after each create, read, update, or delete operation. The database schema remains the final authority for uniqueness, nullability, and relationships.
<?php
$insert = $pdo->prepare(
'INSERT INTO users (name, email) VALUES (:name, :email)'
);
$insert->execute([
'name' => $name,
'email' => $email,
]);
$userId = (int) $pdo->lastInsertId();
<?php
$select = $pdo->prepare(
'SELECT id, name, email FROM users ORDER BY id DESC LIMIT :limit'
);
$select->bindValue('limit', 10, PDO::PARAM_INT);
$select->execute();
$users = $select->fetchAll();
<?php
$update = $pdo->prepare(
'UPDATE users SET email = :email WHERE id = :id'
);
$update->execute(['email' => $email, 'id' => $userId]);
if ($update->rowCount() === 0) {
// The row was missing or the value was unchanged.
}
<?php
$delete = $pdo->prepare('DELETE FROM users WHERE id = :id');
$delete->execute(['id' => $userId]);
$deleted = $delete->rowCount() === 1;
<?php
$pdo->beginTransaction();
try {
$order->execute(['user_id' => $userId]);
$orderId = (int) $pdo->lastInsertId();
$item->execute(['order_id' => $orderId, 'product_id' => $productId]);
$pdo->commit();
} catch (Throwable $exception) {
if ($pdo->inTransaction()) {
$pdo->rollBack();
}
throw $exception;
}
Group dependent writes in one transaction and commit only after every statement succeeds. Roll back in a catch block, log a server-side correlation ID, and show the user a controlled message. Do not hold a transaction open while waiting for another HTTP service or browser action.
For updates and deletes, include the record identity in a bound parameter and verify affected rows. A zero count can mean the record was absent or the submitted values already matched; define that behavior in the application instead of reporting success blindly.
A prepared statement prevents SQL injection in values; it does not validate business rules or authorize a record. Check ownership in the same operation, and let UNIQUE, FOREIGN KEY, CHECK, and NOT NULL constraints protect races that application checks cannot prevent.
For an editable record, include a version number or previous updated_at value in the UPDATE predicate. If no row changes, reload and report a conflict instead of silently overwriting another user's edit. Retry deadlocks only when the whole transaction is safe to repeat.
0 of 2 checked
Try this next
0 of 2 completed
Explore 500+ free tutorials across 20+ languages and frameworks.