Introduction: Why Do You Need a REST API in PHP?
REST API (Representational State Transfer) is an architectural style that allows different applications to communicate with each other via HTTP. Today, no modern web service can do without an API: mobile applications, SPA frontends, integrations with payment systems — all of this requires a fast and clear interface for data exchange.
PHP remains one of the most popular languages for backend development. You can write a full-fledged REST API in pure PHP without bulky frameworks — it will take you no more than 30 minutes. In this article, we will walk through a practical example with CRUD operations (Create, Read, Update, Delete) for managing a To-Do list.
1. Environment Setup and Project Structure
For this you will need:
- A local server (Open Server, XAMPP, MAMP, or the built-in PHP server)
- PHP version 7.4 or higher
- A code editor (VS Code, PhpStorm)
Create a root folder rest-api-php and inside it the following files:
rest-api-php/├── index.php (entry point, router)├── config.php (database settings)├── api/│ ├── tasks.php (CRUD for tasks)│ └── helpers.php (helper functions)└── .htaccess (redirect requests to index.php)1.1. Setting up .htaccess for Clean URLs
To route all requests to a single entry point, create a .htaccess file in the root:
RewriteEngine OnRewriteCond %{REQUEST_FILENAME} !-fRewriteCond %{REQUEST_FILENAME} !-dRewriteRule ^(.*)$ index.php [QSA,L]If you are using the built-in PHP server, simply run it from the project folder: php -S localhost:8000.
2. Creating the Router and Basic API
Open index.php — this is our main handler. It will analyze the HTTP method and URI and call the necessary functions.
2.1. index.php — Entry Point
<?phpheader("Content-Type: application/json; charset=UTF-8");header("Access-Control-Allow-Origin: *");header("Access-Control-Allow-Methods: GET, POST, PUT, DELETE, OPTIONS");header("Access-Control-Allow-Headers: Content-Type, Authorization");
require_once 'config.php';require_once 'api/helpers.php';
$method = $_SERVER['REQUEST_METHOD'];$uri = parse_url($_SERVER['REQUEST_URI'], PHP_URL_PATH);$uri = rtrim($uri, '/');
// Simple routingif ($uri === '/api/tasks') { require_once 'api/tasks.php'; handleTasks($method);} elseif (preg_match('/^\\/api\\/tasks\\/(\\d+)$/', $uri, $matches)) { require_once 'api/tasks.php'; handleTask($method, (int)$matches[1]);} else { sendResponse(['error' => 'Endpoint not found'], 404);}?>We handle two routes: /api/tasks (list/create) and /api/tasks/{id} (specific task).
2.2. helpers.php — Helper Functions
<?phpfunction sendResponse($data, $status = 200) { http_response_code($status); echo json_encode($data, JSON_UNESCAPED_UNICODE); exit;}
function getJsonInput() { $input = file_get_contents('php://input'); return json_decode($input, true) ?? [];}?>3. Working with the Database and CRUD Operations
Let's create a simple tasks table in MySQL:
CREATE TABLE tasks ( id INT AUTO_INCREMENT PRIMARY KEY, title VARCHAR(255) NOT NULL, status ENUM('pending', 'completed') DEFAULT 'pending', created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP);File config.php:
<?php$host = 'localhost';$dbname = 'rest_api_db';$username = 'root';$password = '';
try { $pdo = new PDO("mysql:host=$host;dbname=$dbname;charset=utf8", $username, $password); $pdo->setAttribute(PDO::ATTR_ERRMODE, PDO: