APIs allow software systems to talk to each other. A RESTful API follows a set of rules for structuring requests and responses. In this tutorial, you’ll learn how to build a simple REST API using plain PHP.
Table of Contents
- What Is a RESTful API?
- Project Setup
- Directory Structure
- Create the .htaccess File
- Routing Requests
- Build the Controller
- Handle API Methods (GET, POST, PUT, DELETE)
- Return JSON Responses
- Test Your API
- Conclusion
What Is a RESTful API?
REST stands for Representational State Transfer. A RESTful API uses standard HTTP methods to perform operations:
- GET – fetch data
- POST – add new data
- PUT – update existing data
- DELETE – remove data
Each request must return a structured response, usually in JSON format.
Project Setup
Create a new folder for the project:
mkdir php-rest-api
cd php-rest-api
You need:
- PHP 7.4+ (or 8.x)
- Apache with mod_rewrite enabled
- A tool like Postman for testing
Directory Structure
Create this structure:
php-rest-api/
├── api/
│ └── index.php
├── .htaccess
└── data.json
- index.php: main API logic
- data.json: mock database
- .htaccess: rewrite rules for clean URLs
Create the .htaccess File
Enable clean URLs and route all requests to index.php.
# .htaccess
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^ api/index.php [QSA,L]
Make sure AllowOverride All is enabled in your Apache config.
Routing Requests
In api/index.php, route requests by URL and method.
<?php
header("Content-Type: application/json");
$method = $_SERVER['REQUEST_METHOD'];
$request = explode("/", trim($_SERVER['PATH_INFO'] ?? '', "/"));
$resource = $request[0] ?? null;
$id = $request[1] ?? null;
require_once 'controller.php';
handleRequest($method, $resource, $id);
Build the Controller
Create a controller.php file inside api/.
<?php
function handleRequest($method, $resource, $id) {
if ($resource !== 'items') {
http_response_code(404);
echo json_encode(["error" => "Resource not found"]);
return;
}
$data = json_decode(file_get_contents(__DIR__ . '/../data.json'), true);
switch ($method) {
case 'GET':
if ($id === null) {
echo json_encode($data);
} else {
$item = $data[$id] ?? null;
if ($item) {
echo json_encode($item);
} else {
http_response_code(404);
echo json_encode(["error" => "Item not found"]);
}
}
break;
case 'POST':
$input = json_decode(file_get_contents("php://input"), true);
$id = uniqid();
$data[$id] = $input;
file_put_contents(__DIR__ . '/../data.json', json_encode($data, JSON_PRETTY_PRINT));
http_response_code(201);
echo json_encode(["id" => $id]);
break;
case 'PUT':
if ($id === null || !isset($data[$id])) {
http_response_code(404);
echo json_encode(["error" => "Item not found"]);
return;
}
$input = json_decode(file_get_contents("php://input"), true);
$data[$id] = $input;
file_put_contents(__DIR__ . '/../data.json', json_encode($data, JSON_PRETTY_PRINT));
echo json_encode(["success" => true]);
break;
case 'DELETE':
if ($id === null || !isset($data[$id])) {
http_response_code(404);
echo json_encode(["error" => "Item not found"]);
return;
}
unset($data[$id]);
file_put_contents(__DIR__ . '/../data.json', json_encode($data, JSON_PRETTY_PRINT));
echo json_encode(["success" => true]);
break;
default:
http_response_code(405);
echo json_encode(["error" => "Method not allowed"]);
}
}
Handle API Methods (GET, POST, PUT, DELETE)
Use tools like Postman or curl:
GET All Items
GET /items
GET Single Item
GET /items/{id}
POST New Item
POST /items
Content-Type: application/json
{
"name": "New Item",
"price": 10
}
PUT Update Item
PUT /items/{id}
Content-Type: application/json
{
"name": "Updated Item",
"price": 20
}
DELETE Item
DELETE /items/{id}
Return JSON Responses
The API uses header("Content-Type: application/json") and echo json_encode(...) to return data in a machine-readable format.
Test Your API
You can test it using:
- Postman: GUI tool for API testing
- curl: command-line tool
- JavaScript fetch() or Axios in the browser
Conclusion
You just built a fully working RESTful API in PHP. You handled routing, methods, and JSON responses—all without a framework. This is great for learning or small-scale projects.
Next steps:
- Connect to a real database (MySQL or SQLite)
- Add authentication (JWT, API key)
- Add validation and error handling
Thank you for reading.
Top comments (0)