Restler
Zero-boilerplate REST API framework for PHP 8+. Auto-generates routes, docs, validation.
Install / Use
/learn @Luracast/RestlerREADME
Restler v6
Write your API logic in PHP. Get routing, validation, and OpenAPI docs—automatically.
Production-ready since 2010. Battle-tested. Now rebuilt for modern PHP 8+ with async superpowers.
use Luracast\Restler\Restler;
use Luracast\Restler\Routes;
class Products {
function get(int $id): array {
return Database::findProduct($id);
}
}
Routes::mapApiClasses([Products::class]);
(new Restler)->handle();
That's it. You just created a REST API that:
- ✅ Automatically validates
$idas an integer - ✅ Returns JSON by default
- ✅ Handles routing (
GET /products/123) - ✅ Generates OpenAPI/Swagger docs
- ✅ Provides proper HTTP status codes
- ✅ Supports content negotiation (configure other formats as needed)
No controllers. No routing files. No configuration. Just PHP.
Why Restler in 2025?
🎯 Zero Boilerplate
While other frameworks make you write controllers, routes, DTOs, validation rules, and transformers—Restler uses PHP reflection to do it all automatically. Write business logic, not plumbing.
// Laravel/Symfony: 50+ lines of controllers, routes, requests, resources
// Restler: 5 lines
class Users {
function create(string $email, string $name): User {
return User::create(compact('email', 'name'));
}
}
⚡ Async Performance
Run on Swoole/OpenSwoole for 10-20x throughput vs traditional PHP-FPM. Or use ReactPHP for true async I/O. Deploy to AWS Lambda for serverless scale.
# Traditional PHP-FPM: ~1,000 req/sec
# Swoole/OpenSwoole: ~15,000 req/sec (same code!)
composer swoole-server
🌐 Multi-Format Output
JSON is the default format. Configure additional formats (XML, CSV, Excel, HTML) via Routes::setOverridingResponseMediaTypes(). Perfect for:
- Mobile apps → JSON (default)
- Legacy systems → XML
- Data exports → CSV/Excel
- Admin panels → HTML with Blade/Twig
curl api.example.com/products/123 # JSON (default)
curl api.example.com/products/123.xml # XML (if configured)
curl api.example.com/products.csv # CSV (if configured)
curl api.example.com/products.xlsx # Excel (if configured)
🚀 Modern PHP 8+
Built for PHP 8 with attributes, union types, named arguments, and strict typing. PSR-7 and PSR-11 compliant.
use Luracast\Restler\Attribute\{Get, Post};
class Orders {
#[Get('orders/{id}')]
function getOrder(int $id): Order|null {
return Order::find($id);
}
#[Post('orders')]
function createOrder(string $product, int $quantity = 1): Order {
return Order::create(compact('product', 'quantity'));
}
}
📚 Auto-Generated Docs
OpenAPI 3.0 (Swagger) docs generated from your PHPDoc comments. Interactive API explorer included.
class Products {
/**
* Get product details
*
* @param int $id Product ID
* @return Product product information
* @throws 404 Product not found
*/
function get(int $id): Product {
return Product::findOrFail($id);
}
}
// Visit /explorer for interactive Swagger UI
Real-World Use Cases
🏢 Internal APIs & Microservices
Perfect for building internal APIs that need to integrate with various systems. Multi-format support means you can serve JSON to your React app and XML to that ancient CRM system—from the same endpoint.
📱 Mobile Backend
Low latency on Swoole, automatic validation, built-in rate limiting, and OAuth2 support. Everything you need for a production mobile backend.
📊 Data Export APIs
Built-in CSV and Excel streaming support. Export millions of rows without running out of memory using generators.
function exportUsers(): Generator {
foreach (User::cursor() as $user) {
yield $user->toArray();
}
}
// GET /users.csv streams all users as CSV
// GET /users.xlsx downloads Excel file
🔗 Legacy System Integration
Need to modernize an old PHP app? Add Restler to get a REST API instantly. Works alongside existing code—no rewrite needed.
Quick Start
Install
composer require luracast/restler:^6.0
Create Your First API (3 files)
1. API Class (api/Hello.php)
<?php
class Hello {
function sayHello(string $name = 'World'): string {
return "Hello, $name!";
}
function getTime(): array {
return ['time' => date('Y-m-d H:i:s'), 'timezone' => date_default_timezone_get()];
}
}
2. Gateway (public/index.php)
<?php
require __DIR__ . '/../vendor/autoload.php';
Luracast\Restler\Routes::mapApiClasses([Hello::class]);
(new Luracast\Restler\Restler)->handle();
3. URL Rewriting (.htaccess or nginx.conf)
# Apache
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ index.php [QSA,L]
Test It
# Start server
php -S localhost:8080 -t public
# Try your API
curl http://localhost:8080/hello/sayHello/Restler
# Output: "Hello, Restler!"
curl http://localhost:8080/hello/getTime
# Output: {"time":"2025-01-15 10:30:45","timezone":"UTC"}
curl http://localhost:8080/hello/getTime.xml
# Output: <?xml version="1.0"?><response><time>2025-01-15 10:30:45</time>...
That's it! You have a working REST API with automatic routing, validation, and multi-format support.
Production Deployment
Traditional (Apache/Nginx + PHP-FPM)
Standard deployment. Works everywhere. ~1,000-2,000 req/sec depending on hardware.
// Enable production mode for route caching
$api = new Restler(productionMode: true);
High Performance (Swoole/OpenSwoole)
10-20x faster than PHP-FPM. Persistent connections, coroutines, built-in HTTP server.
# Install extension (choose one)
pecl install swoole # Original
pecl install openswoole # Fork with same API
# Run server
php public/index_swoole.php
Benchmarks: 15,000+ req/sec on modest hardware (vs ~1,000 for PHP-FPM)
Async I/O (ReactPHP)
True non-blocking async operations. Perfect for I/O-heavy workloads (database, HTTP calls, etc.).
composer react-server
Serverless (AWS Lambda)
Zero-downtime deploys, automatic scaling, pay-per-request pricing.
# Uses Bref for Laravel-style Lambda deployment
vendor/bin/bref deploy
See public/index_lambda.php for complete example.
Event-Driven (Workerman)
Alternative to Swoole with pure PHP implementation (no extension required).
php public/index_workerman.php start
What's New in v6
🔥 Breaking Changes from v5
- PHP 8.0+ required (was PHP 7.4)
- PSR-7 HTTP messages (modern request/response objects)
- PSR-11 Container (standard dependency injection)
- Stricter typing (full PHP 8 type hints)
✨ New Features
Modern PHP 8 Support
- ✅ Attributes (
#[Get],#[Post], etc.) - ✅ Union types (
string|int,User|null) - ✅ Named arguments
- ✅ Constructor property promotion
- ✅ Match expressions
- ✅ Enums
Async & Performance
- ✅ Swoole/OpenSwoole integration (10-20x faster)
- ✅ ReactPHP async server
- ✅ Workerman event-driven server
- ✅ AWS Lambda serverless support
- ✅ Generator streaming for large datasets (CSV, Excel)
- ✅ Route caching & opcode optimization
Enhanced Security
- ✅ Secure session serialization (JSON, not
unserialize()) - ✅ JSONP callback validation (XSS prevention)
- ✅ Template injection protection
- ✅ Configurable CORS with proper defaults
- ✅ Built-in rate limiting
- ✅ OAuth 2.0 server support
Developer Experience
- ✅ GraphQL support
- ✅ Excel export (XLSX streaming)
- ✅ OpenAPI 3.0 spec generation
- ✅ Interactive API Explorer (Swagger UI)
- ✅ Better error messages
- ✅ Blade, Twig, Mustache template engines
- ✅ Modern DI container with auto-wiring
Multi-Format Support
All formats work automatically—just add file extension to URL:
- JSON (default)
- XML
- YAML
- CSV (with streaming)
- Excel (XLSX)
- HTML (with templates)
- AMF (Flash/Flex)
- Plist (iOS/macOS)
Advanced Examples
API Versioning
// v1/Users.php
namespace v1;
class Users {
function get(int $id): array {
return ['id' => $id, 'name' => 'John'];
}
}
// v2/Users.php
namespace v2;
class Users {
function get(int $id): User {
return User::with('profile')->find($id);
}
}
// index.php
use Luracast\Restler\Routes;
Routes::mapApiClasses([
'v1/users' => 'v1\\Users',
'v2/users' => 'v2\\Users'
]);
Usage:
curl api.example.com/v1/users/123 # Old format
curl api.example.com/v2/users/123 # New format with profile
Authentication & Rate Limiting
use Luracast\Restler\Contracts\AuthenticationInterface;
class ApiKeyAuth implements AuthenticationInterface {
public function __isAuthenticated(): bool {
$key = $_SERVER['HTTP_X_API_KEY'] ?? null;
return $key && ApiKey::validate($key);
}
}
use Luracast\Restler\Restler;
use Luracast\Restler\Routes;
Routes::addAuthenticator(ApiKeyAuth::class);
Routes::setFilters(RateLimit::class); // Built-in rate limiting
Routes::mapApiClasses([ProtectedAPI::class]);
(new Restler)->handle();
Database Integration
class Products {
/**
* List all products with pagination
*
* @param int $page Page number (default: 1)
* @param int $limit Items per page (default: 20)
*/
function index(i
Related Skills
node-connect
338.7kDiagnose OpenClaw node connection and pairing failures for Android, iOS, and macOS companion apps
frontend-design
83.6kCreate distinctive, production-grade frontend interfaces with high design quality. Use this skill when the user asks to build web components, pages, or applications. Generates creative, polished code that avoids generic AI aesthetics.
openai-whisper-api
338.7kTranscribe audio via OpenAI Audio Transcriptions API (Whisper).
commit-push-pr
83.6kCommit, push, and open a PR



