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

Ddd Apiplatform Bundle Laravel Package

alexandrebulete/ddd-apiplatform-bundle

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Setup

  1. Install the Bundle

    composer require alexandrebulete/ddd-apiplatform-bundle
    

    Ensure your config/bundles.php includes:

    AlexandreBulete\DddApiPlatformBundle\DddApiPlatformBundle::class => ['all' => true],
    
  2. Register the Bridge The bundle auto-wires ddd-apiplatform-bridge services, including the Paginator for state providers.

  3. First Use Case: Paginated Query via State Provider Create a state provider for a DDD query (e.g., GetPostsQuery) and return a Paginator:

    use AlexandreBulete\DddApiPlatformBridge\State\Paginator;
    use ApiPlatform\State\ProviderInterface;
    
    class GetPostsProvider implements ProviderInterface {
        public function provide(Operation $operation, array $uriVariables, array $context) {
            $posts = $this->queryBus->ask(new GetPostsQuery());
            return new Paginator($posts, $operation->getPaginationContext());
        }
    }
    

    Tag it in your API resource:

    # config/api_platform/resources.yaml
    App\Entity\Post:
        collectionOperations:
            get:
                method: 'GET'
                state: App\State\GetPostsProvider
    

Implementation Patterns

1. State Provider Workflow

  • Input: Use Operation to access pagination context (e.g., ?page=2&limit=10).
  • Processing: Delegate to a DDD query (e.g., QueryBus) and wrap results in Paginator.
  • Output: API Platform auto-handles pagination headers (X-Total-Count, Link).

Example with filtering:

public function provide(Operation $operation, array $uriVariables) {
    $filters = $operation->getPaginationContext()['filters'] ?? [];
    $query = new GetFilteredPostsQuery($filters);
    $posts = $this->queryBus->ask($query);
    return new Paginator($posts, $operation->getPaginationContext());
}

2. Integration with DDD Layers

  • Domain Layer: Define queries (e.g., GetPostsQuery) in your domain.
  • Application Layer: Implement state providers to bridge DDD queries to API Platform.
  • Infrastructure Layer: Use Paginator to standardize pagination across endpoints.

Example project structure:

/src
  /Domain/Post/Query/GetPostsQuery.php
  /Application/State/GetPostsProvider.php
  /Infrastructure/ApiPlatform/Resources/Post.yaml

3. Reusing Paginator

Extend Paginator for custom logic (e.g., nested pagination):

class NestedPaginator extends Paginator {
    public function __construct(array $items, array $context, private int $maxDepth = 2) {
        parent::__construct($items, $context);
    }
    // Custom logic...
}

4. Configuration Tips

  • Pagination Context: Access via $operation->getPaginationContext() to dynamically adjust queries.
  • Serialization: Ensure your DDD entities are serializable (e.g., via #[ApiResource]).

Gotchas and Tips

Pitfalls

  1. Pagination Context Mismatch

    • Issue: Paginator expects page/limit in $context. If missing, API Platform throws errors.
    • Fix: Validate context in your provider:
      $context = $operation->getPaginationContext();
      if (empty($context['page'])) $context['page'] = 1;
      
  2. QueryBus Dependency

    • Issue: Forgetting to inject QueryBusInterface causes runtime errors.
    • Fix: Use autowiring or explicit constructor binding:
      public function __construct(private QueryBusInterface $queryBus) {}
      
  3. Entity Serialization

    • Issue: DDD entities may lack #[ApiResource] or serialization groups.
    • Fix: Annotate entities or use #[Groups] for partial serialization.

Debugging

  • Log Pagination Context:
    \Log::debug('Pagination Context:', $operation->getPaginationContext());
    
  • Validate Paginator Inputs: Ensure $items is an array/iterable and $context contains page/limit.

Extension Points

  1. Custom Paginator Classes Override Paginator to add features (e.g., caching, analytics):

    class AnalyticsPaginator extends Paginator {
        public function __construct(array $items, array $context) {
            parent::__construct($items, $context);
            $this->trackUsage(); // Custom logic
        }
    }
    
  2. Dynamic State Providers Use Symfony’s compiler pass to auto-register providers based on DDD queries:

    // src/Kernel.php
    $container->registerForAutoconfiguration(GetPostsProvider::class)
        ->addTag('api_platform.state_provider');
    
  3. Testing Mock QueryBus and Operation in unit tests:

    $operation = $this->createMock(Operation::class);
    $operation->method('getPaginationContext')->willReturn(['page' => 1, 'limit' => 10]);
    

Configuration Quirks

  • Bundle Order: Ensure DddApiPlatformBundle loads after ApiPlatformBundle in bundles.php.
  • PHP 8.2+: The bundle enforces strict types; use #[ReturnTypeWillChange] if migrating from older PHP.

```markdown
## Performance Considerations
- **Pagination Early:** Apply filtering/sorting in the DDD query (e.g., `GetFilteredPostsQuery`) to reduce database load.
- **Lazy Loading:** Use `Paginator` with lazy-loaded collections (e.g., Doctrine `Criteria`) for large datasets.
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.
jayeshmepani/jpl-moshier-ephemeris-php
elnasnato/laraliveui
labrodev/rest-sdk
sampaui/sampaui
babelqueue/php-sdk
facebook/capi-param-builder-php
babelqueue/symfony
hamzi/corewatch
minionfactory/raw-hydrator
hexters/coinpayment
rjcodes/rjcms
act-training/laravel-permissions-manager
alimarchal/laravel-chart-of-accounts
babenkoivan/elastic-scout-driver
mkwebdesign/filament-watchdog-v5
renatomarinho/laravel-page-speed
zedmagdy/filament-business-hours
renatovdemoura/blade-elements-ui
devgeek/beacon-admin
benjamin-rqt/data-watcher-bundle