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)