Introduction: Why a REST API in PHP is Fast and Simple
\n\nREST (Representational State Transfer) is an architectural style that has become the standard for creating web services. Many beginner developers are afraid to implement an API, considering it a complex task. In reality, you can write a full-fledged REST API in PHP in just 30 minutes if you follow the right structure.
\n\nIn this guide, we will create a simple but functional API for managing a to-do list. You will learn how to handle HTTP methods (GET, POST, PUT, DELETE), work with JSON, and build routing. All code examples are ready to run.
\n\nWhat you will get after reading:
\n- \n
- A working REST API in pure PHP without frameworks \n
- An understanding of RESTful architecture principles \n
- A ready-made structure for scaling the project \n
Step 1: Setting Up the Project Structure and Database
\n\nFirst, let's create a simple folder structure. We will need just one PHP file for routing (index.php) and a database configuration file (config.php).
Project Structure
\nrest-api-todo/\n│\n├── index.php (main router)\n├── config.php (database connection)\n└── .htaccess (URL rewriting setup)\n\nCreating the MySQL Database
\nExecute this SQL query in phpMyAdmin or via the console:
\nCREATE DATABASE todo_api;\n\nUSE todo_api;\n\nCREATE TABLE tasks (\n id INT AUTO_INCREMENT PRIMARY KEY,\n title VARCHAR(255) NOT NULL,\n completed BOOLEAN DEFAULT FALSE,\n created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP\n);\n\nINSERT INTO tasks (title) VALUES \n('Learn PHP'), \n('Write a REST API'), \n('Publish an article');\n\nconfig.php File
\n<?php\n// config.php\nheader('Content-Type: application/json');\nheader('Access-Control-Allow-Origin: *');\nheader('Access-Control-Allow-Methods: GET, POST, PUT, DELETE');\nheader('Access-Control-Allow-Headers: Content-Type');\n\n$host = 'localhost';\n$dbname = 'todo_api';\n$username = 'root';\n$password = '';\n\ntry {\n $pdo = new PDO("mysql:host=$host;dbname=$dbname;charset=utf8", $username, $password);\n $pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);\n} catch(PDOException $e) {\n echo json_encode(['error' => 'Database connection error: ' . $e->getMessage()]);\n exit;\n}\n?>\n\nStep 2: Creating a Single Entry Point (Router)
\n\nIn the index.php file, we will implement routing. It will handle the URL and redirect requests to the appropriate functions.
index.php File (Full Code)
\n<?php\nrequire_once 'config.php';\n\n$method = $_SERVER['REQUEST_METHOD'];\n$request = explode('/', trim($_SERVER['PATH_INFO'] ?? '/', '/'));\n\n// Determine the task ID if provided\n$id = isset($request[0]) && is_numeric($request[0]) ? (int)$request[0] : null;\n\n// Handling different HTTP methods\nswitch($method) {\n case 'GET':\n if ($id) {\n getTask($pdo, $id);\n } else {\n getTasks($pdo);\n }\n break;\n \n case 'POST':\n createTask($pdo);\n break;\n \n case 'PUT':\n if ($id) {\n updateTask($pdo, $id);\n } else {\n http_response_code(400);\n echo json_encode(['error' => 'Task ID not provided']);\n }\n break;\n \n case 'DELETE':\n if ($id) {\n deleteTask($pdo, $id);\n } else {\n http_response_code(400);\n echo json_encode(['error' => 'Task ID not provided']);\n }\n break;\n \n default:\n http_response_code(405);\n echo json_encode(['error' => 'Method not supported']);\n}\n\n// --- Function Implementation ---\n\nfunction getTasks($pdo) {\n $stmt = $pdo->query("SELECT * FROM tasks ORDER BY created_a