Practical examples of creating a REST API with PHP (step‑by‑step)
PHP isn’t trendy on tech Twitter, but it quietly powers a huge chunk of the web. With PHP 8+, typed properties, attributes, and better performance, it’s more than capable of running clean, modern REST APIs. The best examples of creating a REST API with PHP today usually combine:
- A simple front controller (single entry point)
- Clear routing (manual or via a framework)
- JSON request/response handling
- Proper HTTP status codes
- Middleware‑style layers for auth, validation, and logging
Let’s walk through concrete, real examples rather than vague theory.
Bare‑bones example of a PHP REST endpoint (no framework)
This is the classic “hello API” example of creating a REST API with PHP: a single index.php that responds with JSON.
<?php
// public/index.php
declare(strict_types=1);
header('Content-Type: application/json');
header('Access-Control-Allow-Origin: *');
\(method = \)_SERVER['REQUEST_METHOD'];
\(path = parse_url(\)_SERVER['REQUEST_URI'], PHP_URL_PATH);
if (\(path === '/api/time' && \)method === 'GET') {
echo json_encode([
'server_time' => (new DateTimeImmutable())->format(DateTimeInterface::ATOM),
]);
exit;
}
http_response_code(404);
echo json_encode(['error' => 'Not Found']);
This tiny snippet shows several important ideas that appear repeatedly in real examples of creating a REST API with PHP:
- One entry point (
index.php) - Routing based on method and path
- JSON output with correct headers
- Meaningful HTTP codes (200 vs 404)
From here, we can grow into something that resembles a real‑world API.
Real examples of creating a REST API with PHP for CRUD operations
Most APIs boil down to CRUD over HTTP. Let’s look at a more realistic example of a tasks API using plain PHP and PDO.
Folder structure example:
api/
public/
index.php
src/
Database.php
TaskController.php
vendor/
Database connection (src/Database.php):
<?php
// src/Database.php
declare(strict_types=1);
class Database
{
public static function getConnection(): PDO
{
$dsn = 'mysql:host=localhost;dbname=tasks_db;charset=utf8mb4';
$user = 'api_user';
$pass = 'secret';
$options = [
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,
];
return new PDO(\(dsn, \)user, \(pass, \)options);
}
}
Controller example (src/TaskController.php):
<?php
// src/TaskController.php
declare(strict_types=1);
require_once __DIR__ . '/Database.php';
class TaskController
{
public function list(): void
{
$db = Database::getConnection();
\(stmt = \)db->query('SELECT id, title, completed FROM tasks ORDER BY id DESC');
\(tasks = \)stmt->fetchAll();
echo json_encode($tasks);
}
public function create(array $data): void
{
if (empty($data['title'])) {
http_response_code(422);
echo json_encode(['error' => 'Title is required']);
return;
}
$db = Database::getConnection();
\(stmt = \)db->prepare('INSERT INTO tasks (title, completed) VALUES (:title, 0)');
\(stmt->execute(['title' => \)data['title']]);
http_response_code(201);
echo json_encode([
'id' => (int)$db->lastInsertId(),
'title' => $data['title'],
'completed' => false,
]);
}
}
Front controller routing example (public/index.php):
<?php
// public/index.php
declare(strict_types=1);
header('Content-Type: application/json');
require_once __DIR__ . '/../src/TaskController.php';
\(method = \)_SERVER['REQUEST_METHOD'];
\(path = parse_url(\)_SERVER['REQUEST_URI'], PHP_URL_PATH);
$controller = new TaskController();
if (\(path === '/api/tasks' && \)method === 'GET') {
$controller->list();
exit;
}
if (\(path === '/api/tasks' && \)method === 'POST') {
$input = json_decode(file_get_contents('php://input'), true) ?? [];
\(controller->create(\)input);
exit;
}
http_response_code(404);
echo json_encode(['error' => 'Not Found']);
This is one of the best examples of creating a REST API with PHP in its simplest useful form: it has routing, validation, and database access, but no framework overhead.
JWT auth example of creating a REST API with PHP
Modern APIs rarely stay public. A very common example of creating a REST API with PHP in 2024 is adding JWT (JSON Web Token) authentication so mobile apps or SPAs can authenticate statelessly.
Using the popular firebase/php-jwt library:
composer require firebase/php-jwt
Token generation (login endpoint):
use Firebase\JWT\JWT;
use Firebase\JWT\Key;
$secret = 'super-secret-key';
// After validating user credentials...
$payload = [
'sub' => $userId,
'iat' => time(),
'exp' => time() + 3600, // 1 hour
];
\(jwt = JWT::encode(\)payload, $secret, 'HS256');
echo json_encode(['token' => $jwt]);
Token validation middleware‑style example:
function requireAuth(): array
{
$headers = getallheaders();
\(authHeader = \)headers['Authorization'] ?? '';
if (!str_starts_with($authHeader, 'Bearer ')) {
http_response_code(401);
echo json_encode(['error' => 'Missing token']);
exit;
}
\(token = substr(\)authHeader, 7);
try {
\(decoded = JWT::decode(\)token, new Key('super-secret-key', 'HS256'));
return (array) $decoded;
} catch (Throwable $e) {
http_response_code(401);
echo json_encode(['error' => 'Invalid token']);
exit;
}
}
You can then call requireAuth() at the top of protected routes. This pattern shows up in many real examples of creating a REST API with PHP for production systems.
Pagination and filtering: examples include real‑world list endpoints
Once you have more than a handful of records, you need pagination. Here’s an example of adding simple page and per_page parameters to the tasks endpoint.
public function list(): void
{
$db = Database::getConnection();
\(page = max(1, (int)(\)_GET['page'] ?? 1));
\(perPage = max(1, min(100, (int)(\)_GET['per_page'] ?? 20)));
\(offset = (\)page - 1) * $perPage;
\(stmt = \)db->prepare('SELECT SQL_CALC_FOUND_ROWS id, title, completed
FROM tasks
ORDER BY id DESC
LIMIT :limit OFFSET :offset');
\(stmt->bindValue(':limit', \)perPage, PDO::PARAM_INT);
\(stmt->bindValue(':offset', \)offset, PDO::PARAM_INT);
$stmt->execute();
\(tasks = \)stmt->fetchAll();
\(total = (int)\)db->query('SELECT FOUND_ROWS()')->fetchColumn();
echo json_encode([
'data' => $tasks,
'meta' => [
'page' => $page,
'per_page' => $perPage,
'total' => $total,
'total_pages' => (int)ceil(\(total / \)perPage),
],
]);
}
This is a concrete example of how real APIs expose large datasets without overwhelming clients.
Framework‑based examples of creating a REST API with PHP
In 2024–2025, most production PHP APIs use a framework. The best examples of creating a REST API with PHP at scale usually mention at least one of these:
- Laravel for full‑stack development and batteries‑included tooling
- Symfony for enterprise‑grade structure and reusable components
- Slim or Lumen for lightweight microservices
Laravel example of a REST API resource
Laravel’s artisan commands generate a lot of boilerplate for you.
Route definition (routes/api.php):
use App\Http\Controllers\TaskController;
Route::middleware('auth:sanctum')->group(function () {
Route::apiResource('tasks', TaskController::class);
});
Controller example (app/Http/Controllers/TaskController.php):
class TaskController extends Controller
{
public function index(Request $request)
{
return Task::query()
->orderByDesc('id')
->paginate($request->get('per_page', 20));
}
public function store(Request $request)
{
\(validated = \)request->validate([
'title' => ['required', 'string', 'max:255'],
]);
$task = Task::create([
'title' => $validated['title'],
'completed' => false,
]);
return response()->json($task, 201);
}
}
This is a higher‑level example of creating a REST API with PHP where the framework handles routing, validation, and pagination.
Slim example for microservices
With Slim, you can build a tiny API that still feels modern.
use Psr\Http\Message\ServerRequestInterface as Request;
use Psr\Http\Message\ResponseInterface as Response;
use Slim\Factory\AppFactory;
require __DIR__ . '/../vendor/autoload.php';
$app = AppFactory::create();
\(app->get('/api/health', function (Request \)request, Response $response) {
$payload = json_encode(['status' => 'ok', 'time' => time()]);
\(response->getBody()->write(\)payload);
return $response->withHeader('Content-Type', 'application/json');
});
$app->run();
If you’re looking for small, focused examples of creating a REST API with PHP for microservices or serverless functions, Slim is a good fit.
2024–2025 trends that affect PHP REST API design
A few trends are shaping how new APIs are written:
- Typed PHP everywhere. New examples of creating a REST API with PHP almost always use
declare(strict_types=1);and typed properties. - JSON:API and OpenAPI. Teams document their APIs with OpenAPI specs and often follow JSON:API‑style responses for consistency.
- Security first. OWASP guidelines for input validation, rate limiting, and auth are standard reading. For general security awareness, the U.S. Cybersecurity & Infrastructure Security Agency publishes accessible guidance.
- API observability. Logging, tracing, and metrics are treated as first‑class concerns rather than afterthoughts.
If you’re building something that interacts with regulated sectors (health, finance, education), you’ll also want to pay attention to domain‑specific guidance. For example, the Office for Civil Rights at HHS outlines HIPAA rules that indirectly influence how healthcare APIs handle authentication and logging.
Validation and error‑handling examples
APIs live or die on their error handling. Clients need predictable formats and clear messages.
Here’s a small example of a reusable JSON response helper:
function jsonResponse(mixed \(data, int \)status = 200): void
{
http_response_code($status);
header('Content-Type: application/json');
echo json_encode($data, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES);
}
You can then turn earlier examples of creating a REST API with PHP into cleaner code:
if (empty($data['title'])) {
jsonResponse(['error' => 'Title is required'], 422);
return;
}
Consistent error structures make it much easier for frontend developers and mobile clients to integrate.
Putting it together: best examples of PHP REST APIs in practice
To recap, here are several concrete patterns you can adapt:
- A single‑file time API for quick testing or internal tools
- A PDO‑based CRUD API for small apps and prototypes
- JWT‑secured endpoints for mobile and SPA backends
- Paginated list endpoints for large datasets
- Laravel
apiResourcecontrollers for full‑stack projects - Slim‑based microservices for focused, fast APIs
These are not theoretical; they’re all real examples of creating a REST API with PHP that you can run today. Start with the smallest example of functionality you need, then layer in auth, pagination, and validation as your project grows.
If you want to go deeper on API design patterns in general, the Harvard University CS50 materials often include up‑to‑date examples of web programming concepts, and the National Institute of Standards and Technology publishes guidelines that are helpful when you start worrying about security, encryption, and data integrity in production APIs.
FAQ: examples of common PHP REST API questions
Q: Can you show an example of a PHP REST API that returns JSON for a single record?
Yes. For a GET /api/tasks/123 endpoint using PDO:
public function show(int $id): void
{
$db = Database::getConnection();
\(stmt = \)db->prepare('SELECT id, title, completed FROM tasks WHERE id = :id');
\(stmt->execute(['id' => \)id]);
\(task = \)stmt->fetch();
if (!$task) {
jsonResponse(['error' => 'Task not found'], 404);
return;
}
jsonResponse($task);
}
Q: Are there good examples of versioning a REST API in PHP?
A common pattern is to prefix routes with /v1, /v2, and route them to different controllers or folders, for example /api/v1/tasks and /api/v2/tasks. In Laravel, you might group routes by namespace; in plain PHP, you might map /api/v1 to src/V1/ and /api/v2 to src/V2/. This lets you ship new behavior without breaking older clients.
Q: How do I test these examples of creating a REST API with PHP?
Use tools like curl, Postman, or HTTPie to hit your endpoints. For automated tests, PHPUnit works well with both plain PHP and frameworks. You can spin up a local PHP server with php -S localhost:8000 -t public and run requests against it.
Q: Is PHP still a good choice for new REST APIs in 2025?
If your team already knows PHP or you’re building on top of an existing PHP codebase, yes. Many of the best examples of creating a REST API with PHP today run behind major CMSs, legacy apps, or as part of Laravel‑based platforms. If your stack is already invested in PHP, it’s entirely reasonable to keep your APIs there.
These patterns should give you enough real examples to start building, not just reading about, REST APIs in PHP.
Related Topics
Real‑world examples of using Composer for PHP dependency management
Real-world examples of hosting open source SaaS with PHP
The best examples of simple PHP function examples for beginners
The best examples of creating a PHP session: 3 practical examples for real projects
The best examples of learn PHP arrays and loops with practical examples
Real‑world examples of practical PHP date and time functions examples
Explore More PHP Code Snippets
Discover more examples and insights in this category.
View All PHP Code Snippets