Installation
composer require bulatronic/api-kit
Enable the bundle in config/bundles.php:
return [
// ...
Bulatronic\ApiKit\ApiKitBundle::class => ['all' => true],
];
First Controller
Extend AbstractApiController and use built-in response helpers:
use Bulatronic\ApiKit\Controller\AbstractApiController;
class UserController extends AbstractApiController
{
public function index(): JsonResponse
{
return $this->jsonSuccess(['users' => User::all()]);
}
}
Automatic Exception Handling
Throw ApiException anywhere (e.g., in services) to return standardized errors:
throw new ApiException('User not found', 404, ['user_id' => $id]);
Success Responses
Use jsonSuccess() for consistent payloads:
return $this->jsonSuccess(['data' => $user], 201); // 201 Created
Error Responses
Exceptions (including ApiException) auto-convert to JSON:
// Throws automatically formatted error
throw new ApiException('Invalid input', 400, ['errors' => $validator->getErrors()]);
Request Payload Validation
Use #[MapRequestPayload] with Symfony’s validator:
#[MapRequestPayload]
class CreateUserDto
{
#[Assert\NotBlank]
public string $name;
}
Query String Validation
Use #[MapQueryString] for query params:
#[MapQueryString]
class UserFilterDto
{
#[Assert\Positive]
public int $limit = 10;
}
Multipart Validation Annotate upload fields in DTOs:
#[MapUploadedFile(maxSize: '1M', allowedTypes: ['image/jpeg'])]
public ?UploadedFile $avatar;
Automatic Error Handling
Invalid uploads trigger ApiException with details (e.g., maxSize violations).
Trait-Based Shortcuts
Use ApiControllerTrait for lightweight controllers:
use Bulatronic\ApiKit\Controller\ApiControllerTrait;
class HealthCheckController
{
use ApiControllerTrait;
public function check(): JsonResponse
{
return $this->jsonSuccess(['status' => 'ok']);
}
}
Service Layer Integration
Controllers delegate logic to services, which throw ApiException for errors:
// Service
public function deleteUser(int $id): void
{
if (!$user = $this->userRepository->find($id)) {
throw new ApiException('User not found', 404);
}
// ...
}
Exception Details
ApiException includes a details array for debugging:
throw new ApiException('Error', 500, ['trace' => $e->getTraceAsString()]);
Validation Errors
DTO validation errors are auto-formatted in the errors field of responses.
Response Format
Override the default JSON format by extending ApiKitBundle and redefining the response_formatter service.
Global Exception Mappers
Extend ApiExceptionMapper to customize how exceptions are converted to JSON.
Custom DTO Mappers
Implement DtoMapperInterface for non-standard payloads (e.g., GraphQL inputs).
File Upload Rules
Create custom validators for #[MapUploadedFile] by implementing UploadedFileValidatorInterface.
Circular Dependencies
Avoid injecting AbstractApiController into services—use ApiException instead for error handling.
DTO Overhead For simple APIs, consider skipping DTOs and using raw request data with manual validation.
Symfony Version Lock
Requires Symfony 7.4+ and PHP 8.2+. Downgrading may break features like #[MapRequestPayload].
How can I help you explore Laravel packages today?