This blog post demonstrates how to create a simple single-page CRUD (Create, Read, Update, Delete) API using only core PHP. The purpose of this project is to provide a clear and straightforward example for beginners who want to understand how to develop a RESTful API in PHP without using frameworks.
System Requirements
To run this project, ensure you have the following installed:
- PHP: This example uses the latest PHP features and syntax available in version 8.2.
- MariaDB: The example requires a MariaDB or MySQL instance for the database operations.
- cURL: A command-line tool for sending HTTP requests. Note that any REST client can be used to test the API endpoints.
- Composer: The
composer.json
file is included to provide context for PHP server requirements and dependencies, but it is optional for running this project.
Setup Instructions
- Create the
api.php
file: Place theapi.php
file on any machine that has PHP configured. - Configure Database Connection: Ensure the database connection settings in the
api.php
file are correctly set for your database instance. This will allow the API to connect to the database and perform necessary operations. - Run the PHP Server: Start the PHP built-in server in the same folder as
api.php
to use the example REST calls as-is:
php -S localhost:8080
The Code
<?php
/*
* CRUD API Example in core PHP.
*
* This script provides a basic implementation of a CRUD (Create, Read, Update, Delete) API
* using PHP, PDO for database interactions, and JSON for data exchange. The API supports
* creating, reading, updating, and deleting customer records in a MySQL database.
* It also includes endpoints for setting up and tearing down the customers table, which are
* available for illustrative purposes and convenience in this example, but should never be
* placed in a production environment.
*/
$host = '127.0.0.1';
$dbname = 'testing';
$username = 'username';
$password = 'password';
try {
/* Establish database connection */
$pdo = new PDO("mysql:host=$host;dbname=$dbname", $username, $password);
$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
} catch (PDOException $exception) {
die('Database connection failed: ' . $exception->getMessage());
}
/**
* Validate user input data for creating or updating a customer.
*
* @param string[] $data The data to validate
*
* @return string[] The array of validation errors
*/
function validateInput(array $data): array
{
$errors = [];
if (empty($data['firstName'])) {
$errors[] = 'First name is required';
}
if (empty($data['lastName'])) {
$errors[] = 'Last name is required';
}
if (empty($data['email']) || !filter_var($data['email'], FILTER_VALIDATE_EMAIL)) {
$errors[] = 'Valid email is required';
}
return $errors;
}
/* Retrieve HTTP method and path segments */
$method = $_SERVER['REQUEST_METHOD'];
$path = parse_url($_SERVER['REQUEST_URI'], PHP_URL_PATH);
$segments = explode('/', trim($path, '/'));
/* Determine the resource and customer ID (if any) from the URL */
$resource = $segments[1] ?? '';
$customerId = $segments[2] ?? '';
switch ($resource) {
case 'up':
if ($method === 'POST') {
try {
/* Create 'customers' table if it doesn't exist */
$sql = 'CREATE TABLE IF NOT EXISTS customers (
customerId CHAR(36) DEFAULT uuid() PRIMARY KEY,
firstName VARCHAR(255) NOT NULL,
lastName VARCHAR(255) NOT NULL,
email VARCHAR(255) NOT NULL,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
)';
$pdo->exec($sql);
echo json_encode(['message' => 'Table created successfully']);
} catch (PDOException $exception) {
http_response_code(500);
echo json_encode(['error' => 'Failed to create table: ' . $exception->getMessage()]);
}
} else {
http_response_code(405);
echo json_encode(['error' => 'Method not allowed']);
}
break;
case 'down':
if ($method === 'DELETE') {
try {
/* Drop 'customers' table if it exists */
$sql = 'DROP TABLE IF EXISTS customers';
$pdo->exec($sql);
echo json_encode(['message' => 'Table dropped successfully']);
} catch (PDOException $exception) {
http_response_code(500);
echo json_encode(['error' => 'Failed to drop table: ' . $exception->getMessage()]);
}
} else {
http_response_code(405);
echo json_encode(['error' => 'Method not allowed']);
}
break;
case 'customers':
switch ($method) {
case 'GET':
if ($customerId) {
/* Read one customer */
$stmt = $pdo->prepare('SELECT * FROM customers WHERE customerId = :customerId');
$stmt->execute(['customerId' => $customerId]);
$customer = $stmt->fetch(PDO::FETCH_ASSOC);
if ($customer) {
echo json_encode($customer);
} else {
http_response_code(404);
echo json_encode(['error' => 'Customer not found']);
}
} else {
/* Read all customers */
$stmt = $pdo->query('SELECT * FROM customers');
$customers = $stmt->fetchAll(PDO::FETCH_ASSOC);
echo json_encode($customers);
}
break;
case 'POST':
/* Create a new customer */
$data = json_decode(file_get_contents('php://input'), true);
$errors = validateInput($data);
if (empty($errors)) {
$stmt = $pdo->prepare('INSERT INTO customers (firstName, lastName, email) VALUES (:firstName, :lastName, :email)');
$stmt->execute([
'firstName' => $data['firstName'],
'lastName' => $data['lastName'],
'email' => $data['email']
]);
/* Fetch the customerId of the newly created customer */
$stmt = $pdo->query('SELECT customerId FROM customers ORDER BY created_at DESC LIMIT 1');
$customerId = $stmt->fetchColumn();
echo json_encode(['message' => 'Customer created successfully', 'customerId' => $customerId]);
} else {
http_response_code(400);
echo json_encode(['errors' => $errors]);
}
break;
case 'PUT':
if ($customerId) {
/* Update an existing customer */
$stmt = $pdo->prepare('SELECT COUNT(*) FROM customers WHERE customerId = :customerId');
$stmt->execute(['customerId' => $customerId]);
$customerExists = $stmt->fetchColumn();
if ($customerExists) {
$data = json_decode(file_get_contents('php://input'), true);
$errors = validateInput($data);
if (empty($errors)) {
$stmt = $pdo->prepare('UPDATE customers SET firstName = :firstName, lastName = :lastName, email = :email WHERE customerId = :customerId');
$stmt->execute([
'firstName' => $data['firstName'],
'lastName' => $data['lastName'],
'email' => $data['email'],
'customerId' => $customerId
]);
echo json_encode(['message' => 'Customer updated successfully']);
} else {
http_response_code(400);
echo json_encode(['errors' => $errors]);
}
} else {
http_response_code(404);
echo json_encode(['error' => 'Customer not found']);
}
} else {
http_response_code(400);
echo json_encode(['error' => 'Customer ID is required']);
}
break;
case 'DELETE':
if ($customerId) {
/* Delete an existing customer */
$stmt = $pdo->prepare('DELETE FROM customers WHERE customerId = :customerId');
$stmt->execute(['customerId' => $customerId]);
echo json_encode(['message' => 'Customer deleted successfully']);
} else {
http_response_code(400);
echo json_encode(['error' => 'Customer ID is required']);
}
break;
default:
http_response_code(405);
echo json_encode(['error' => 'Method not allowed']);
break;
}
break;
default:
http_response_code(404);
echo json_encode(['error' => 'Endpoint not found']);
break;
}
Operation Sequence Diagram
Below is a sequence diagram that shows the flow of API requests and interactions with the database.
API Endpoints
This API provides the following endpoints:
1. Bring the Application Up
- URL:
/api.php/up
- Method:
POST
- Description: Initializes the application and creates the
customers
table in the database.
curl --request POST \
--url http://localhost:8080/api.php/up \
--header 'Content-Type: application/json'
Example Output:
{
"message": "Table created successfully"
}
2. Create a New Customer
- URL:
/api.php/customers
- Method:
POST
- Description: Creates a new customer record.
curl --request POST \
--url http://localhost:8080/api.php/customers \
--header 'Content-Type: application/json' \
--data '{
"firstName": "John",
"lastName": "Doe",
"email": "john.doe@example.com"
}'
Example Output:
{
"message": "Customer created successfully",
"customerId": "2090a31b-64aa-11ef-9cca-0242ac120002"
}
3. Update an Existing Customer
- URL:
/api.php/customers/{customerId}
- Method:
PUT
- Description: Updates an existing customer record by ID.
curl --request PUT \
--url http://localhost:8080/api.php/customers/2090a31b-64aa-11ef-9cca-0242ac120002 \
--header 'Content-Type: application/json' \
--data '{
"firstName": "Janet",
"lastName": "Smith",
"email": "jane.smith@example.com"
}'
Example Output:
{
"message": "Customer updated successfully"
}
4. Retrieve a Customer by ID
- URL:
/api.php/customers/{customerId}
- Method:
GET
- Description: Retrieves a customer record by ID.
curl --request GET \
--url http://localhost:8080/api.php/customers/2090a31b-64aa-11ef-9cca-0242ac120002
Example Output:
{
"customerId": "2090a31b-64aa-11ef-9cca-0242ac120002",
"firstName": "Janet",
"lastName": "Smith",
"email": "jane.smith@example.com",
"created_at": "2024-08-27 19:25:32"
}
5. Retrieve All Customers
- URL:
/api.php/customers
- Method:
GET
- Description: Retrieves all customer records.
curl --request GET \
--url http://localhost:8080/api.php/customers/
Example Output:
[
{
"customerId": "2090a31b-64aa-11ef-9cca-0242ac120002",
"firstName": "Janet",
"lastName": "Smith",
"email": "jane.smith@example.com",
"created_at": "2024-08-27 19:25:32"
},
{
"customerId": "9b9a1019-65c0-11ef-87f6-0242ac140002",
"firstName": "John",
"lastName": "Marsh",
"email": "john.marsh@example.com",
"created_at": "2024-08-29 04:38:59"
}
]
6. Delete a Customer
- URL:
/api.php/customers/{customerId}
- Method:
DELETE
- Description: Deletes a customer record by ID.
curl --request DELETE \
--url http://localhost:8080/api.php/customers/2090a31b-64aa-11ef-9cca-0242ac120002
Example Output:
{
"message": "Customer deleted successfully"
}
7. Bring the Application Down
- URL:
/api.php/down
- Method:
DELETE
- Description: Cleans up and destroys the
customers
table in the database.
curl --request DELETE \
--url http://localhost:8080/api.php/down \
--header 'Content-Type: application/json'
Example Output:
{
"message": "Table dropped successfully"
}
Conclusion
This example demonstrates a fundamental RESTful API using core PHP and MariaDB. It is an excellent starting point for beginners looking to understand the basics of API development without requiring a framework. You can use this code to build upon and expand your knowledge of RESTful services in PHP.
No comments:
Post a Comment