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

Core Laravel Package

api-platform/core

API Platform Core lets you quickly build hypermedia-driven REST and GraphQL APIs in PHP/Symfony. Supports JSON-LD, Hydra, OpenAPI v2/v3, JSON:API, HAL, and RFC7807. Extensible, high-performance, API-first.

View on GitHub
Deep Wiki
Context7
## Getting Started

### Minimal Setup in Laravel
1. **Installation**
   ```bash
   composer require api-platform/core
   composer require api-platform/laravel

Add ApiPlatform\Laravel\ApiPlatformServiceProvider::class to config/app.php providers.

  1. First Resource Annotate an Eloquent model with #[ApiResource]:

    use ApiPlatform\Metadata\ApiResource;
    use ApiPlatform\Metadata\Get;
    use ApiPlatform\Metadata\GetCollection;
    
    #[ApiResource(
        operations: [
            new Get(),
            new GetCollection(),
        ],
        normalizationContext: ['groups' => ['read']],
        denormalizationContext: ['groups' => ['write']],
    )]
    class Book extends Model
    {
        // ...
    }
    

    Run migrations and test with:

    php artisan api:context:generate
    php artisan serve
    

    Access /api/books to see auto-generated API.

  2. First Use Case

    • CRUD Endpoints: Instantly available for all #[ApiResource] classes.
    • Pagination: Automatic cursor-based pagination (e.g., /api/books?page=2).
    • Documentation: OpenAPI/Swagger at /api/docs.

Implementation Patterns

Core Workflows

  1. Resource Design

    • Annotations: Use #[ApiResource] with operations (e.g., #[Post], #[Put]) and #[ApiProperty] for fine-grained control.
    • DTOs: Decouple input/output with #[ApiResource(input: BookInput::class)].
    • Groups: Organize serialization with #[Groups(['read'])] on properties.
  2. Filtering & Sorting

    • Doctrine Filters: Enable with #[ApiFilter(SearchFilter::class)] or #[ApiFilter(ComparisonFilter::class)].
    • Custom Filters: Implement FilterInterface:
      use ApiPlatform\Metadata\OperationFilter;
      use ApiPlatform\Doctrine\Orm\Filter\AbstractFilter;
      
      #[ApiFilter(BookFilter::class)]
      class Book extends Model {}
      
      class BookFilter extends AbstractFilter
      {
          protected function filterProperty(string $property, $value, QueryBuilder $queryBuilder, string $resourceClass, Operation $operation = null, array $context = []): void
          {
              if ($property === 'published') {
                  $queryBuilder->andWhere('b.published_at >= :date')
                      ->setParameter('date', $value);
              }
          }
      }
      
  3. State Providers

    • Custom Logic: Implement StateProviderInterface for complex operations:
      use ApiPlatform\State\ProviderInterface;
      
      class BookStateProvider implements ProviderInterface
      {
          public function process($data, Operation $operation, array $uriVariables = [], array $context = []): void
          {
              if ($operation->getMethod() === 'POST') {
                  $data->setAuthorId(auth()->id());
              }
          }
      }
      
    • Register via #[ApiResource(state: BookStateProvider::class)].
  4. GraphQL Integration

    • Enable with #[ApiResource(graphql: ['query' => true, 'mutation' => true])].
    • Use #[GraphQLQuery] or #[GraphQLMutation] for custom operations.
  5. Validation

    • Constraints: Use Symfony’s #[Assert\...] or #[ApiProperty(validationConstraints: [new Assert\NotBlank()])].
    • Partial Updates: Configure denormalizationContext:
      #[ApiResource(
          denormalizationContext: ['validation_groups' => ['partial']]
      )]
      
  6. Security

    • Roles: Use #[ApiResource(security: "is_granted('ROLE_ADMIN')")].
    • JWT/OAuth: Integrate with #[ApiResource(security: "is_granted('ROLE_USER')")] and middleware.
  7. Performance

    • Pagination: Use #[ApiResource(paginationItemsPerPage: 20)].
    • Caching: Leverage #[ApiResource(cacheHeaders: ['max-age' => 3600])].
    • Eager Loading: Configure #[ApiResource(iriConverter: BookIriConverter::class)] for custom IRIs.

Integration Tips

  1. Laravel-Specific

    • Eloquent Models: Use #[ApiResource] directly on models (no need for separate DTOs for simple CRUD).
    • Laravel Policies: Integrate with #[ApiResource(security: 'authorize:book')].
    • Events: Listen to ApiPlatform\EventListener\Event (e.g., PRE_WRITE, POST_READ).
  2. Symfony Interop

    • Dependency Injection: Use api_platform.iri_converter, api_platform.state_provider, etc.
    • Messenger: Decorate ApiPlatform\State\ProviderInterface for async processing.
  3. Testing

    • Client: Use ApiPlatform\Symfony\Tests\Functional\TestTrait:
      use ApiPlatform\Symfony\Tests\Functional\TestTrait;
      
      class BookTest extends TestCase
      {
          use TestTrait;
      
          public function testGetCollection(): void
          {
              $response = static::createClient()->request('GET', '/api/books');
              $this->assertResponseIsSuccessful();
          }
      }
      
    • Fixtures: Use ApiPlatform\Symfony\Bundle\Test\Fixtures\Loader\DoctrineFixturesLoader.

Gotchas and Tips

Pitfalls

  1. IRI Generation

    • Issue: Custom iriConverter may break pagination or relations.
    • Fix: Ensure IriConverterInterface implements getIriFromResource() and getResourceFromIri() correctly.
    • Debug: Check api_platform.iri_converter service for collisions.
  2. Circular References

    • Issue: Infinite loops in serialization with bidirectional relations.
    • Fix: Use #[ApiProperty(serialize: false)] or configure normalizationContext:
      #[ApiResource(
          normalizationContext: ['enable_max_depth' => true, 'max_depth' => 3]
      )]
      
  3. Filter Conflicts

    • Issue: Multiple filters on the same property (e.g., SearchFilter + ComparisonFilter).
    • Fix: Use #[ApiFilter(SearchFilter::class, properties: ['title'])] to scope properties.
  4. GraphQL Schema Conflicts

    • Issue: Naming collisions between REST and GraphQL fields.
    • Fix: Explicitly map fields in #[GraphQLField] or use #[ApiProperty(graphql: ['name' => 'custom_name'])].
  5. Laravel-Specific Quirks

    • Issue: #[ApiResource] on abstract models may cause metadata errors.
    • Fix: Exclude abstract models from API or use #[ApiResource(shortName: 'concrete_model')].
    • Issue: Eloquent casts not respected in denormalization.
    • Fix: Use #[ApiProperty(denormalizationContext: ['groups' => ['cast']])] or implement a custom StateProvider.
  6. Performance

    • Issue: N+1 queries with nested relations.
    • Fix: Use #[ApiResource(iriConverter: CustomIriConverter::class)] with eager loading or #[ApiProperty(serialize: false)] for heavy relations.
    • Debug: Enable Doctrine profiling:
      $this->container->get('doctrine')->getConnection()->getConfiguration()->setSQLLogger(new \Doctrine\DBAL\Logging\EchoSQLLogger());
      
  7. Caching Headers

    • Issue: Incorrect ETag or Last-Modified headers.
    • Fix: Implement CacheHeadersProviderInterface or use #[ApiResource(cachePublic: true)].

Debugging Tips

  1. Metadata Dumps

    • Dump resource metadata for debugging:
      $metadata = $this->container->get('api_platform.metadata.resource.metadata_factory')->getMetadataForClass(Book::class);
      dd($metadata);
      
  2. Event Listeners

    • Log events for state transitions:
      use ApiPlatform\EventListener\Event;
      
      $event->setResult($modifiedData); // In PRE_WRITE
      $event->setResponseHeader('X-Custom-Header', 'value'); // In POST_READ
      
  3. GraphQL Debugging

    • Enable GraphQL Playground at /api/graphql and inspect queries.
    • Check api_platform.graphql.schema_factory for schema generation issues.
  4. Validation Errors

    • Use ValidationException for detailed error messages:
      throw new ValidationException($validator->getErrors());
      
  5. Symfony Profiler

    • Enable api_platform.profiler to
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.
emuniq/filament-browser-notifications
syriable/filament-translator
hungnm28/livewire-form
wenprise/eloquent
crudly/encrypted
fadion/bouncy
cuci/prototurk-sdk
gos/pubsub-router-bundle
cuci/prototurk-sdk-symfony
clementtalleu/easyadmin-markdown-bundle
codeflextech/permission-manager
karnoweb/livewire-datepicker
sayedenam/sayed-dashboard
milito/query-filter
apiboxsym/user-bundle
apiboxsym/health-check-bundle
jayeshmepani/jpl-moshier-ephemeris-php
elnasnato/laraliveui
labrodev/rest-sdk
sampaui/sampaui