Weave Code
Code Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Apibundle Laravel Package

redhotmagma/apibundle

Laravel package that bundles common API building blocks—helpers, responses, request validation, and boilerplate to speed up creating consistent JSON endpoints. Designed to reduce repetitive setup and keep API structure standardized across projects.

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Setup

  1. Installation

    composer require redhotmagma/apibundle
    

    Add the bundle to config/bundles.php (Symfony) or config/app.php (Laravel via Symfony bridge):

    RedHotMagma\ApiBundle\RedHotMagmaApiBundle::class => ['all' => true],
    
  2. First Use Case: Basic Entity Transformation Define a simple DTO (Data Transfer Object) and map it to a Doctrine entity:

    // src/Dto/UserDto.php
    namespace App\Dto;
    use RedHotMagma\ApiBundle\Dto\AbstractDto;
    
    class UserDto extends AbstractDto
    {
        public ?int $id;
        public string $name;
        public string $email;
    }
    

    Create a transformer to handle conversion:

    // src/Transformer/UserTransformer.php
    namespace App\Transformer;
    use App\Dto\UserDto;
    use App\Entity\User;
    use RedHotMagma\ApiBundle\Transformer\AbstractTransformer;
    
    class UserTransformer extends AbstractTransformer
    {
        public function transformToEntity(array $data): User
        {
            $user = new User();
            $user->setName($data['name']);
            $user->setEmail($data['name']);
            return $user;
        }
    
        public function transformToArray(User $entity): array
        {
            return [
                'id' => $entity->getId(),
                'name' => $entity->getName(),
                'email' => $entity->getEmail(),
            ];
        }
    }
    
  3. Register Transformer Bind the transformer in a service provider (e.g., AppServiceProvider):

    public function register()
    {
        $this->app->bind(UserTransformer::class);
    }
    
  4. First API Endpoint Use the transformer in a controller:

    // src/Controller/UserController.php
    use App\Dto\UserDto;
    use App\Transformer\UserTransformer;
    use RedHotMagma\ApiBundle\Dto\DtoManager;
    
    class UserController extends AbstractController
    {
        public function __construct(
            private DtoManager $dtoManager,
            private UserTransformer $transformer
        ) {}
    
        public function create(UserDto $dto): JsonResponse
        {
            $entity = $this->transformer->transformToEntity($dto->toArray());
            // Save entity logic here...
            return $this->json($this->transformer->transformToArray($entity));
        }
    }
    

Implementation Patterns

Common Workflows

  1. DTO-Driven API Development

    • Request Validation: Use Symfony’s Validator component with DTOs:
      use Symfony\Component\Validator\Constraints as Assert;
      
      class UserDto extends AbstractDto
      {
          #[Assert\NotBlank]
          public string $name;
      
          #[Assert\Email]
          public string $email;
      }
      
    • Automatic Binding: Leverage DtoManager to bind DTOs to request data:
      public function update(Request $request, UserDto $dto)
      {
          // $dto is automatically populated from $request
      }
      
  2. Transformer Layer

    • Separation of Concerns: Keep transformation logic decoupled from business logic.
    • Reusable Transformers: Extend AbstractTransformer for nested entities:
      class PostTransformer extends AbstractTransformer
      {
          public function transformToArray(Post $post): array
          {
              return [
                  'id' => $post->getId(),
                  'title' => $post->getTitle(),
                  'author' => $this->getTransformer(UserTransformer::class)
                      ->transformToArray($post->getAuthor()),
              ];
          }
      }
      
  3. Dependency Injection

    • Service Binding: Bind transformers and DTOs as services:
      $this->app->bind(UserTransformer::class);
      $this->app->bind(UserDto::class);
      
    • Lazy Loading: Use DtoManager to dynamically resolve DTOs:
      $dto = $this->dtoManager->create(UserDto::class, $request->all());
      
  4. API Resource Handling

    • Collection Transformers: Handle arrays of entities:
      public function transformToArrayCollection(array $entities): array
      {
          return array_map([$this, 'transformToArray'], $entities);
      }
      
    • Pagination: Integrate with Symfony’s Pagination component:
      use Knp\Component\Pager\PaginatorInterface;
      
      public function index(PaginatorInterface $paginator, int $page = 1)
      {
          $users = $paginator->paginate(
              $this->userRepository->findAll(),
              $page,
              10
          );
          return $this->json($this->transformer->transformToArrayCollection($users));
      }
      
  5. Event-Driven Extensions

    • Pre/Post Transform Events: Subscribe to events for custom logic:
      // src/EventSubscriber/TransformerSubscriber.php
      use RedHotMagma\ApiBundle\Event\PreTransformEvent;
      use Symfony\Component\EventDispatcher\EventSubscriberInterface;
      
      class TransformerSubscriber implements EventSubscriberInterface
      {
          public static function getSubscribedEvents()
          {
              return [
                  PreTransformEvent::class => 'onPreTransform',
              ];
          }
      
          public function onPreTransform(PreTransformEvent $event)
          {
              if ($event->getEntity() instanceof User) {
                  $event->setData(['name' => strtoupper($event->getData()['name'])]);
              }
          }
      }
      

Gotchas and Tips

Pitfalls and Debugging

  1. Circular References

    • Issue: Transforming entities with circular references (e.g., UserPost with bidirectional relations) causes infinite loops.
    • Fix: Use #[ORM\HasLifecycleCallbacks] or manually handle cycles in transformers:
      public function transformToArray(User $user): array
      {
          $data = [
              'id' => $user->getId(),
              'name' => $user->getName(),
          ];
          if (!$user->isProcessed()) { // Custom flag
              $data['posts'] = $this->transformer->transformToArrayCollection($user->getPosts());
              $user->setProcessed(true);
          }
          return $data;
      }
      
  2. DTO Validation Overhead

    • Issue: Overly complex DTO validation can slow down API responses.
    • Tip: Use #[Assert\Callback] for dynamic validation:
      use Symfony\Component\Validator\Context\ExecutionContextInterface;
      
      #[Assert\Callback]
      public function validate(ExecutionContextInterface $context)
      {
          if ($this->email && !str_contains($this->email, 'example.com')) {
              $context->buildViolation('Email must be from example.com')
                      ->atPath('email')
                      ->addViolation();
          }
      }
      
  3. Transformer Caching

    • Issue: Repeated transformations of the same entity can be inefficient.
    • Tip: Implement caching in transformers:
      private array $cache = [];
      
      public function transformToArray(User $user): array
      {
          if (!isset($this->cache[$user->getId()])) {
              $this->cache[$user->getId()] = [
                  'id' => $user->getId(),
                  'name' => $user->getName(),
              ];
          }
          return $this->cache[$user->getId()];
      }
      
  4. Symfony vs. Laravel Quirks

    • Issue: Laravel’s service container differs from Symfony’s, causing binding issues.
    • Fix: Use AbstractBundle to bridge Laravel services:
      // In RedHotMagmaApiBundle
      public function boot()
      {
          $this->container->bind(
              'dto.manager',
              DtoManager::class
          )->inSingleton();
      }
      
  5. Event Dispatcher Conflicts

    • Issue: Events may not fire due to incorrect subscriber binding.
    • Tip: Verify subscribers are registered in services.yaml (Symfony) or AppServiceProvider (Laravel):
      # config/services.yaml
      services:
          App\EventSubscriber\TransformerSubscriber:
              tags: ['kernel.event_subscriber']
      
  6. Doctrine Entity Changes

    • Issue: Entity schema changes break transformers.
    • Tip: Use migrations and update transformers incrementally:
      // Before: $user->getFullName()
      // After: $user->getName() . ' ' . $user->getLastName()
      

Extension Points

  1. Custom DTO Managers
    • Extend DtoManager to add custom logic:
      class CustomDtoManager extends DtoManager
      {
          public function create(string $dtoClass, array $data, bool $validate = true, bool
      
Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
nasirkhan/laravel-sharekit
directorytree/privacy-filter-classifier
directorytree/privacy-filter
datacore/hub-sdk
develia/commons
cuci/prototurk-sdk
cuci/prototurk-sdk-symfony
develia/geo-bundle
dreamzy/livewire-charts
touchestate-sdk/php-sdk
22h/doctrine-garbage-collection-bundle
agtp/agtp-php
agtp/mod-php
splash/sonata-admin
splash/metadata
splash/openapi
splash/scopes
splash/toolkit
testo/output-teamcity
testo/bridge-symfony