How to Write a REST API in PHP in 30 Minutes
REST API (Representational State Transfer) is an architectural style for interaction between components of a distributed application over a network. In modern web development, REST API is the standard for creating backends for mobile applications, SPAs (Single Page Application), and microservices. In this article, we will show you how to write a simple but fully functional REST API in PHP in just 30 minutes.
We will create an API for managing a task list (Todo List) with support for CRUD operations (Create, Read, Update, Delete). You will learn how to organize routing, handle JSON requests, and connect to a MySQL database.
Environment Setup
For this you will need:
- Apache or Nginx web server with PHP 7.4+ support
- MySQL or MariaDB
- Code editor (VS Code, PhpStorm)
- Postman or curl for testing the API
Create the project structure:
todo-api/├── index.php # Entry point (router)├── config.php # Database connection settings├── api/│ └── tasks.php # Task management logic└── .htaccess # URL rewrite settingsStep 1: Configuring .htaccess and Entry Point
Create the .htaccess file to redirect all requests to index.php:
RewriteEngine OnRewriteCond %{REQUEST_FILENAME} !-fRewriteCond %{REQUEST_FILENAME} !-dRewriteRule ^(.*)$ index.php?url=$1 [QSA,L]Now let's create index.php — our main router:
<?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");
// Handle preflight requestsif ($_SERVER['REQUEST_METHOD'] === 'OPTIONS') { http_response_code(200); exit();}
require_once 'config.php';require_once 'api/tasks.php';
$url = isset($_GET['url']) ? rtrim($_GET['url'], '/') : '';$urlParts = explode('/', $url);$resource = $urlParts[0] ?? '';$id = $urlParts[1] ?? null;
switch ($resource) { case 'tasks': $tasks = new Tasks(); echo $tasks->handleRequest($_SERVER['REQUEST_METHOD'], $id); break; default: http_response_code(404); echo json_encode(["message" => "Resource not found"]); break;}?>Step 2: Database Connection
Create config.php with connection settings:
<?phpclass Database { private $host = "localhost"; private $db_name = "todo_api"; private $username = "root"; private $password = ""; public $conn;
public function getConnection() { $this->conn = null; try { $this->conn = new PDO( "mysql:host=" . $this->host . ";dbname=" . $this->db_name, $this->username, $this->password ); $this->conn->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); } catch(PDOException $e) { http_response_code(500); echo json_encode(["message" => "Database connection error"]); exit(); } return $this->conn; }}?>Create the table in MySQL:
CREATE DATABASE todo_api;USE todo_api;
CREATE TABLE tasks ( id INT AUTO_INCREMENT PRIMARY KEY, title VARCHAR(255) NOT NULL, description TEXT, status ENUM('pending', 'completed') DEFAULT 'pending', created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP);Step 3: Implementing CRUD Operations
Create the file api/tasks.php with the main logic: