PHP code example of bulatronic / api-kit

1. Go to this page and download the library: Download bulatronic/api-kit library. Choose the download type require.

2. Extract the ZIP file and open the index.php.

3. Add this code to the index.php.
    
        
<?php
require_once('vendor/autoload.php');

/* Start to develop here. Best regards https://php-download.com/ */

    

bulatronic / api-kit example snippets


public function create(Request $request): JsonResponse
{
    try {
        $dto = $this->serializer->deserialize($request->getContent(), CreatePostDto::class, 'json');
        $errors = $this->validator->validate($dto);
        if (count($errors) > 0) {
            return $this->json(['error' => (string) $errors], 422);
        }
        $result = $this->service->create($dto);
        return $this->json(['success' => true, 'data' => $result], 201);
    } catch (ConflictException $e) {
        return $this->json(['error' => $e->getMessage()], 409);
    } catch (\Throwable $e) {
        $this->logger->error($e->getMessage());
        return $this->json(['error' => 'Internal error'], 500);
    }
}

public function create(#[MapRequestPayload] CreatePostDto $dto): JsonResponse
{
    return $this->respondCreated($this->service->create($dto));
}

final readonly class CreatePostDto
{
    public function __construct(
        #[Assert\NotBlank]
        #[Assert\Length(min: 3, max: 255)]
        public string $title,

        #[Assert\NotBlank]
        public string $content,
    ) {}
}

use ApiKit\Controller\AbstractApiController;

#[Route('/api/posts')]
final class PostController extends AbstractApiController
{
    public function __construct(
        private readonly PostService $postService,
    ) {}

    #[Route('', methods: ['GET'])]
    public function list(): JsonResponse
    {
        return $this->respondSuccess($this->postService->findAll());
    }

    #[Route('', methods: ['POST'])]
    public function create(#[MapRequestPayload] CreatePostDto $dto): JsonResponse
    {
        return $this->respondCreated($this->postService->create($dto));
    }

    #[Route('/{id}', methods: ['DELETE'])]
    public function delete(int $id): JsonResponse
    {
        $this->postService->delete($id);
        return $this->respondNoContent();
    }
}

use ApiKit\Controller\ApiControllerTrait;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;

#[Route('/api/posts')]
final class PostController extends AbstractController
{
    use ApiControllerTrait;

    // ... same methods
}

use ApiKit\Exception\ApiException;
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;

final class PostService
{
    public function findOrFail(int $id): Post
    {
        $post = $this->repository->find($id);

        if (null === $post) {
            throw new NotFoundHttpException('Post not found');
        }

        return $post;
    }

    public function create(CreatePostDto $dto): Post
    {
        if ($this->repository->existsByTitle($dto->title)) {
            throw new ApiException(409, 'Post with this title already exists', [
                'field' => 'title',
                'value' => $dto->title,
            ]);
        }

        // ...
    }
}

public function create(#[MapRequestPayload] CreatePostDto $dto): JsonResponse
{
    return $this->respondCreated($this->postService->create($dto));
}

// Success responses
$this->respondSuccess($data, $status = 200, $meta = []);
$this->respondCreated($data, $meta = []);
$this->respondNoContent();

// Error responses
$this->respondError($message, $status = 400, $code = 'ERROR', $details = []);
$this->respondNotFound($message = 'Resource not found');
$this->respondForbidden($message = 'Access forbidden');
$this->respondUnauthorized($message = 'Unauthorized');

public function __construct(
    private readonly ResponseFactory $responseFactory,
) {}

$this->responseFactory->success($data, $statusCode = 200, $meta = []);
$this->responseFactory->created($data, $meta = []);
$this->responseFactory->noContent();
$this->responseFactory->error($message, $code = 'ERROR', $statusCode = 400, $details = []);

use ApiKit\Exception\ApiException;

// Without details
throw new ApiException(409, 'Email already taken');

// With structured details
throw new ApiException(423, 'Account locked', [
    'locked_until'  => $until->format(\DateTimeInterface::ATOM),
    'reason'        => 'too_many_attempts',
]);

use ApiKit\Validator\Constraint\EntityExists;

final readonly class CreateCommentDto
{
    public function __construct(
        #[Assert\NotBlank]
        public string $content,

        #[Assert\Uuid]
        #[EntityExists(User::class)]
        public string $authorId,

        // Search by field other than id
        #[EntityExists(entityClass: Category::class, field: 'slug')]
        public ?string $categorySlug = null,
    ) {}
}