High-performance, async-by-default PHP framework inspired by FastAPI.
- Blazing Fast: Built on OpenSwoole for maximum performance (>15k RPS with full validation).
- Async by Default: Fully supports coroutines and non-blocking I/O.
- Elite Caching: Integrated Symfony Cache with boot-time warmup and native support for Redis, APCu, and Filesystem.
- Pydantic-like Validation: Extensible, type-safe request/response DTO validation using the
Constraintsystem. - Automatic OpenAPI: Generates Swagger UI and OpenAPI JSON automatically.
- Pluggable Database: Use any ORM (Eloquent, Cycle) or raw PDO via Dependency Injection.
composer require fastor/fastorAfter installation, the fastor CLI tool can be installed to your project root by running:
php vendor/bin/fastor initThis creates a ./fastor executable in your root for easier access. It's also always available at vendor/bin/fastor.
Create a main.php:
<?php
$app = app();
$app->get("/hello/{name}", function(string $name) {
return ["message" => "Hello, $name!"];
});
// Auto-validated DTO (No #[Body] needed!)
$app->post("/register", function(UserRequest $req): UserResponse {
return $req; // Automatically mapped to UserResponse
});
$app->run();Run your app:
./fastor run main.phpFastor provides a powerful CLI for running your applications.
./fastor run [file.php] [options]--host <host>: Specify the host (default:0.0.0.0).--port <port>: Specify the port (default:8000).--env <env>: Specify the environment (default:production).
Fastor handles both HTTP and WebSockets on the same port by default. You can disable either protocol if needed:
$app = app();
$app->disableWs(); // Pure HTTP server
$app->disableHttp(); // Pure WebSocket serverFastor uses a "Dependency Injection" pattern for authentication, similar to FastAPI.
use Fastor\Attributes\Auth;
use Fastor\Auth\Bearer;
// 1. Register an auth dependency
$app->registerDependency('auth', new Bearer());
// 2. Use it in your routes
$app->get("/protected", function(#[Auth] string $token) {
return ["token" => $token];
});You can use Fastor\Auth\Bearer or Fastor\Auth\ApiKey, or create your own callable class.
Fastor is database-agnostic. You can plug in any database layer using Dependency Injection.
use Fastor\Depends\Depends;
$app->registerDependency('db', function() {
return new PDO('sqlite:database.sqlite');
});
$app->get("/users", function(#[Depends('db')] PDO $db) {
return $db->query("SELECT * FROM users")->fetchAll(PDO::FETCH_ASSOC);
});Fastor works beautifully with Cycle ORM. Just register the ORM as a dependency:
use Cycle\ORM\ORMInterface;
// 1. Setup and register Cycle
$app->registerDependency(ORMInterface::class, function() {
return $myConfiguredCycleInstance;
});
// 2. Use it in your routes
$app->get("/users", function(ORMInterface $orm) {
return $orm->getRepository(User::class)->findAll();
});Fastor treats validation as a first-class citizen. Most of the time, you don't even need attributes:
use Fastor\Attributes\Body;
use Fastor\Validation\Attributes\{Email, Range};
class UserRequest {
#[Email]
public string $email;
#[Range(18, 99)]
public int $age;
}
class UserResponse {
public string $email;
public bool $status = true;
}
// Automatic Request & Response Validation!
$app->post("/register", function(UserRequest $req): UserResponse {
return $req;
});Fastor can automatically resolve your dependencies. No registration needed for concrete classes!
class UserRepository {
public function find(int $id) { /* ... */ }
}
class UserService {
public function __construct(
private UserRepository $repo
) {}
public function getUser(int $id) {
return $this->repo->find($id);
}
}
// Fastor automatically instantiates UserService and UserRepository!
$app->get("/user/{id}", function(int $id, UserService $service) {
return $service->getUser($id);
});If you need to inject an interface or a pre-configured instance (like a DB connection), use registerDependency.
For a comprehensive showcase of Fastor's capabilities—including simultaneous HTTP/WebSocket handling, hybrid database usage (PDO & Cycle ORM), and complex DTO validation—see the Social Hub Example.
// examples/social_hub.php snippet
$app->post("/posts", function(PostRequest $req, PostService $service, Broadcast $broadcast) {
$post = $service->create($req);
// Notify all WebSocket clients about the new post
$broadcast->emit('new_post', [
'title' => $post->title,
'author' => $post->author->username
]);
return $post;
});Fastor is designed for elite performance in production environments.
When you call $app->run(), Fastor enters a boot() phase. During this phase:
- The Valinor Mapper is pre-initialized and cached.
- All route handlers are scanned, and their Reflection Metadata is pre-calculated.
- Every DTO property is analyzed, and a Pre-compiled Validation Plan is generated.
This ensures that during the request cycle, validation is just a series of high-speed method calls with zero reflective overhead.
Fastor includes a unified caching layer out of the box:
// Setup Redis cache
cache()->redis('redis://localhost');
// Or use the default high-performance file cache
cache()->file('storage/cache');Visit localhost:8000/docs after starting your app to see the automatic Swagger documentation.
MIT