REST APIs in PHP: Building Professional Web Services
REST APIs in PHP: Building Professional Web Services
Specialized Guide by Alaa Amer – Professional Web & App Developer
REST APIs have become the backbone of modern applications. In this article, you'll learn how to build professional APIs using pure PHP with best practices.
2️⃣ Building Simple API Framework
Router Class:
<?php
// classes/Router.php
class Router {
private $routes = [];
public function get($path, $handler) {
$this->addRoute('GET', $path, $handler);
}
public function post($path, $handler) {
$this->addRoute('POST', $path, $handler);
}
public function put($path, $handler) {
$this->addRoute('PUT', $path, $handler);
}
public function delete($path, $handler) {
$this->addRoute('DELETE', $path, $handler);
}
private function addRoute($method, $path, $handler) {
$this->routes[] = [
'method' => $method,
'path' => $path,
'handler' => $handler
];
}
public function resolve() {
$method = $_SERVER['REQUEST_METHOD'];
$path = parse_url($_SERVER['REQUEST_URI'], PHP_URL_PATH);
// Remove /api from beginning if present
$path = preg_replace('#^/api#', '', $path);
foreach ($this->routes as $route) {
if ($route['method'] === $method) {
$pattern = preg_replace('/\{[^}]+\}/', '([^/]+)', $route['path']);
$pattern = '#^' . $pattern . '$#';
if (preg_match($pattern, $path, $matches)) {
array_shift($matches); // Remove full match
return $this->executeHandler($route['handler'], $matches);
}
}
}
return $this->notFound();
}
private function executeHandler($handler, $params = []) {
if (is_callable($handler)) {
return call_user_func_array($handler, $params);
}
if (is_array($handler) && count($handler) === 2) {
list($class, $method) = $handler;
$instance = new $class();
return call_user_func_array([$instance, $method], $params);
}
return $this->notFound();
}
private function notFound() {
http_response_code(404);
return json_encode(['error' => 'Route not found']);
}
}
Response Class:
<?php
// classes/Response.php
class Response {
public static function json($data, $statusCode = 200, $headers = []) {
http_response_code($statusCode);
// Add default headers
header('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');
// Add custom headers
foreach ($headers as $header => $value) {
header("$header: $value");
}
echo json_encode($data, JSON_UNESCAPED_UNICODE);
exit;
}
public static function success($data = null, $message = 'Success', $statusCode = 200) {
$response = [
'success' => true,
'message' => $message,
'timestamp' => date('Y-m-d H:i:s')
];
if ($data !== null) {
$response['data'] = $data;
}
self::json($response, $statusCode);
}
public static function error($message, $statusCode = 400, $errors = null) {
$response = [
'success' => false,
'message' => $message,
'timestamp' => date('Y-m-d H:i:s')
];
if ($errors !== null) {
$response['errors'] = $errors;
}
self::json($response, $statusCode);
}
}
4️⃣ Data Models
<?php
// models/User.php
class User {
private $db;
public function __construct($database) {
$this->db = $database;
}
public function findAll($limit = 10, $offset = 0) {
$stmt = $this->db->prepare("
SELECT id, name, email, created_at
FROM users
ORDER BY created_at DESC
LIMIT :limit OFFSET :offset
");
$stmt->bindParam(':limit', $limit, PDO::PARAM_INT);
$stmt->bindParam(':offset', $offset, PDO::PARAM_INT);
$stmt->execute();
return $stmt->fetchAll(PDO::FETCH_ASSOC);
}
public function findById($id) {
$stmt = $this->db->prepare("
SELECT id, name, email, created_at
FROM users
WHERE id = :id
");
$stmt->bindParam(':id', $id, PDO::PARAM_INT);
$stmt->execute();
return $stmt->fetch(PDO::FETCH_ASSOC);
}
public function create($data) {
$stmt = $this->db->prepare("
INSERT INTO users (name, email, password, created_at)
VALUES (:name, :email, :password, NOW())
");
$data['password'] = password_hash($data['password'], PASSWORD_DEFAULT);
$stmt->bindParam(':name', $data['name']);
$stmt->bindParam(':email', $data['email']);
$stmt->bindParam(':password', $data['password']);
if ($stmt->execute()) {
return $this->findById($this->db->lastInsertId());
}
return false;
}
public function authenticate($email, $password) {
$stmt = $this->db->prepare("
SELECT id, name, email, password
FROM users
WHERE email = :email
");
$stmt->bindParam(':email', $email);
$stmt->execute();
$user = $stmt->fetch(PDO::FETCH_ASSOC);
if ($user && password_verify($password, $user['password'])) {
unset($user['password']); // Remove password from result
return $user;
}
return false;
}
}
6️⃣ Main API File
<?php
// api/index.php
require_once '../config/config.php';
require_once '../classes/Database.php';
require_once '../classes/Router.php';
require_once '../classes/Response.php';
require_once '../classes/JWTAuth.php';
require_once '../models/User.php';
require_once '../controllers/UserController.php';
// Handle CORS
if ($_SERVER['REQUEST_METHOD'] === 'OPTIONS') {
header('Access-Control-Allow-Origin: *');
header('Access-Control-Allow-Methods: GET, POST, PUT, DELETE, OPTIONS');
header('Access-Control-Allow-Headers: Content-Type, Authorization');
http_response_code(200);
exit;
}
$router = new Router();
// Authentication routes
$router->post('/auth/login', [AuthController::class, 'login']);
$router->post('/auth/register', [AuthController::class, 'register']);
// User routes
$router->get('/users', [UserController::class, 'index']);
$router->get('/users/{id}', [UserController::class, 'show']);
$router->post('/users', [UserController::class, 'store']);
// Handle errors
try {
echo $router->resolve();
} catch (Exception $e) {
Response::error('Server error: ' . $e->getMessage(), 500);
}
💡 Performance Optimization Tips
- Use Caching: Redis or Memcached for frequent data
- Database Indexing: Indexes on frequently queried columns
- Rate Limiting: Limit requests per user
- Compression: Compress large responses
- API Versioning: Plan for future versions
Next Step
Learn GraphQL and API Documentation using OpenAPI/Swagger.
📩 Need help building complex APIs?
Article Category
REST APIs in PHP: Building Professional Web Services
Complete guide to developing REST APIs using PHP with best practices, security, and practical examples.
Consultation & Communication
Direct communication via WhatsApp or phone to understand your project needs precisely.
Planning & Scheduling
Creating clear work plan with specific timeline for each project phase.
Development & Coding
Building projects with latest technologies ensuring high performance and security.
Testing & Delivery
Comprehensive testing and thorough review before final project delivery.