Controllers
Basic Controller
php
use Nexphant\Get;
use Nexphant\Post;
use Nexphant\Put;
use Nexphant\Delete;
use Nexphant\Request;
class UserController
{
#[Get('/users')]
public function index()
{
return ['users' => []];
}
#[Get('/users/{id}')]
public function show(Request $request, int $id)
{
return ['user_id' => $id];
}
#[Post('/users')]
public function store(Request $request)
{
$data = $request->json();
return ['created' => true, 'data' => $data];
}
#[Put('/users/{id}')]
public function update(Request $request, int $id)
{
return ['updated' => $id];
}
#[Delete('/users/{id}')]
public function destroy(int $id)
{
return ['deleted' => $id];
}
}Register Controller
php
$app->annotations(UserController::class);Dependency Injection
Controller method parameters are resolved from the DI container automatically. Type-hint any registered service to have it injected.
php
class OrderController
{
#[Post('/orders')]
public function store(Request $request, OrderService $orders, Mailer $mailer)
{
$order = $orders->create($request->json());
$mailer->sendConfirmation($order);
return ['order_id' => $order->id];
}
}Services must be bound in the container before the controller is registered:
php
$app->bind(OrderService::class, fn () => new OrderService());
$app->bind(Mailer::class, fn () => new Mailer(env('MAIL_DSN')));
$app->annotations(OrderController::class);Data Object Validation
Type-hint a Data subclass to get automatic validation before the method is called:
php
use Nexphant\Support\Data;
use Nexphant\Validation\Rules\{Required, Length, Email};
class CreateUserData extends Data
{
#[Required, Email]
public string $email;
#[Required, Length(min: 2, max: 100)]
public string $name;
}
class UserController
{
#[Post('/users')]
public function store(CreateUserData $data)
{
// $data is already validated
return ['email' => $data->email, 'name' => $data->name];
}
}If validation fails, a 422 Unprocessable Entity response is returned automatically with the error details.
Middleware Per Route
Apply middleware to specific controller methods using the #[Middleware] attribute:
php
use Nexphant\Middleware;
class UserController
{
#[Get('/users')]
#[Middleware(AuthMiddleware::class)]
public function index()
{
return ['users' => []];
}
#[Post('/users')]
#[Middleware(AuthMiddleware::class, AdminMiddleware::class)]
public function store(Request $request)
{
return ['created' => true];
}
}Route Parameters
Route parameters are injected by name. Type-casted automatically to int, float, or string.
php
class PostController
{
#[Get('/posts/{postId}/comments/{commentId}')]
public function showComment(int $postId, int $commentId)
{
return ['post' => $postId, 'comment' => $commentId];
}
}Constructor Injection
The controller itself is resolved from the DI container, so constructor injection works too:
php
class ProductController
{
public function __construct(
private readonly ProductRepository $products,
private readonly CacheInterface $cache,
) {}
#[Get('/products')]
public function index()
{
return $this->cache->remember('products', fn () => $this->products->all());
}
}