spiral/framework
Spiral Framework is a high-performance, long-running full-stack PHP framework built for RoadRunner. PSR-compliant components, resident memory kernel, and native support for queues, GRPC, WebSockets, and background workers.
## Getting Started
### Minimal Steps to Begin
1. **Installation**:
```bash
composer create-project spiral/framework my-project
Or add to an existing project:
composer require spiral/framework
First Use Case:
php spiral.php make:controller Home
app/Http/Controller/HomeController.php with a default index() method.Where to Look First:
config/app.php (defines bootloaders, kernel settings).app/Http/routes.php (PSR-15 compatible router).app/Provider/ (bootloaders for services).config/session.php (updated in 3.13.1 for path containment fixes).Bootloader-Based Initialization:
app/Provider/ (e.g., DatabaseProvider.php).@Bootloader attributes or extend BootloaderInterface:
#[Bootloader]
class DatabaseProvider extends Bootloader
{
public function boot(IocContainer $container): void
{
$container->bindSingleton('db', fn() => new PDO(...));
}
}
PSR-15 Middleware:
app/Http/Middleware/:
#[Middleware]
class AuthMiddleware implements MiddlewareInterface
{
public function process(ServerRequestInterface $request, RequestHandlerInterface $handler): ResponseInterface
{
// Logic...
return $handler->handle($request);
}
}
$router->group('/admin', [AuthMiddleware::class], function (Router $router) {
$router->get('/dashboard', [DashboardController::class, 'index']);
});
Session Management (Updated in 3.13.1):
config/session.php:
'handler' => [
'type' => 'file',
'path' => storage_path('framework/sessions'),
'name' => 'spiral_session',
],
$session = $container->get(SessionInterface::class);
$session->start(); // Session ID will now be validated and path containment enforced
Cycle ORM Integration:
app/Entity/ (e.g., User.php).$user = $container->get(UserRepository::class)->find(1);
php spiral.php cycle:migrate
Queue Workers:
app/Job/ (e.g., SendEmailJob.php).$queue->dispatch(new SendEmailJob($user));
rr get queue:consume
CLI Commands:
php spiral.php make:command SendEmail
#[Command(name: 'email:send', description: 'Send an email')]
class SendEmailCommand extends Command
{
#[Argument(name: 'to', description: 'Recipient email')]
private string $to;
protected function execute(): int
{
// Logic...
return self::SUCCESS;
}
}
Event-Driven Architecture:
$dispatcher->dispatch(new UserRegisteredEvent($user));
$dispatcher->listen(UserRegisteredEvent::class, [UserNotifier::class, 'notify']);
spiral/roadrunner-bridge for HTTP, queues, and WebSockets.config/roadrunner.php:
return [
'servers' => [
'http' => [
'addr' => '0.0.0.0:8080',
],
],
];
app/Workflow/ (e.g., OrderProcessingWorkflow.php).spiral/temporal-bridge for distributed task orchestration.php spiral.php make:crud User
config/scaffolder.php.Session Path Containment (Fixed in 3.13.1):
storage_path('framework/sessions') is writable and properly configured in config/session.php.Memory Leaks:
php spiral.php debug:memory
RoadRunner Configuration:
roadrunner.json is properly configured for your environment (e.g., static vs. dynamic workers).QueueInterface).Queue Retries:
config/queue.php:
'retry_policy' => [
'max_attempts' => 3,
'delay' => 1000, // ms
],
RetryPolicyInterceptor for automatic retries:
$queue->addInterceptor(new RetryPolicyInterceptor());
ORM Eager Loading:
$user = $repository->with(['posts'])->find(1);
Middleware Order:
#[Priority] to adjust:
#[Middleware(priority: -100)] // Runs first
class AuthMiddleware implements MiddlewareInterface { ... }
Environment Variables:
.env files in app/Provider/KernelProvider.php:
$container->bindSingleton(EnvironmentInterface::class, fn() => new DotEnv());
Debugging Routes:
php spiral.php debug:routes
$router->get('/debug', function () use ($router) {
return json_encode($router->getRoutes());
});
Container Inspection:
php spiral.php debug:container
$container->has('db') ? $container->get('db') : 'Not bound';
Logging:
config/monolog.php:
'format' => '%datetime% [%level_name%] %message% %context% %extra%',
LogTracer for performance:
$tracer = new LogTracer($logger);
$tracer->start('operation');
// ... code ...
$tracer->finish();
Tokenizer Issues:
php spiral.php tokenizer:validate
php spiral.php tokenizer:info
Session Debugging (3.13.1):
$session = $container->get(SessionInterface::class);
$session->start();
error_log($session->getId()); // Check if ID is valid and properly formatted
Custom Bootloaders:
Bootloader for reusable logic:
class CacheBootloader extends Bootloader
{
public function boot(IocContainer $container): void
{
$container->bindSingleton('cache', fn() => new RedisCache());
}
}
Dynamic Route Patterns:
app/Provider/RoutingProvider.php:
$container->bindSingleton(
RoutePatternRegistryInterface::class,
fn() => new RoutePatternRegistry(['uuid' => '[0-9a-f]{8}-[0
How can I help you explore Laravel packages today?