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

Metadata Laravel Package

api-platform/metadata

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Setup

  1. Installation:

    composer require api-platform/metadata
    

    Add to composer.json if using a monorepo or custom package.

  2. First Use Case: Define a resource class with metadata attributes (e.g., @ApiResource for API Platform integration):

    use ApiPlatform\Metadata\ApiResource;
    use ApiPlatform\Metadata\Get;
    use ApiPlatform\Metadata\GetCollection;
    
    #[ApiResource(
        operations: [
            new Get(),
            new GetCollection(),
        ],
        normalizationContext: ['groups' => ['read']],
    )]
    class Book {}
    
  3. Key Files:

    • src/Metadata/ApiResource.php (core class)
    • src/Operation/OperationInterface.php (for CRUD operations)
    • src/Factory/ResourceFactory.php (for dynamic metadata generation)
  4. Quick Test:

    use ApiPlatform\Metadata\Resource\Factory\ResourceFactory;
    use ApiPlatform\Metadata\Resource\ResourceDescription;
    
    $factory = new ResourceFactory();
    $description = $factory->createFromClass(Book::class);
    var_dump($description->getOperations()); // Inspect metadata
    

Implementation Patterns

1. Metadata-Driven Development

  • Pattern: Use attributes to define API contracts (e.g., @ApiResource, @ApiProperty).
    #[ApiProperty(identifier: true)]
    private ?int $id = null;
    
  • Workflow:
    1. Define metadata in entity classes.
    2. Use ResourceFactory to generate ResourceDescription objects.
    3. Pass descriptions to API Platform’s ApiResource system or custom logic.

2. Dynamic Metadata Generation

  • Pattern: Extend ResourceFactory to generate metadata programmatically.
    class CustomResourceFactory extends ResourceFactory {
        public function createFromClass(string $class): ResourceDescription {
            $description = parent::createFromClass($class);
            $description->addOperation(new CustomOperation());
            return $description;
        }
    }
    
  • Use Case: Override defaults for specific classes (e.g., add a POST operation to all Admin* entities).

3. Integration with API Platform

  • Pattern: Combine with api-platform/core for automatic API generation.
    # config/packages/api_platform.yaml
    api_platform:
        formats:
            jsonld: ['application/ld+json']
        metadata_dirs: ['%kernel.project_dir%/src/Metadata']
    
  • Tip: Use metadata_dirs to auto-load attributes from files (e.g., Book.yaml).

4. Validation and Serialization

  • Pattern: Leverage metadata for validation (e.g., @Assert\NotBlank) and serialization groups.
    #[ApiProperty(
        groups: ['read', 'write'],
        serializationContext: ['groups' => ['read']]
    )]
    private ?string $title = null;
    

5. Testing

  • Pattern: Mock ResourceDescription in unit tests.
    $description = $this->createMock(ResourceDescription::class);
    $description->method('getOperations')->willReturn([new Get()]);
    

Gotchas and Tips

Pitfalls

  1. Attribute Reflection Overhead:

    • Metadata is resolved via reflection at runtime. Cache descriptions in production:
      $cache = new Symfony\Component\Cache\Adapter\FilesystemAdapter();
      $description = $cache->get($class, function() use ($factory, $class) {
          return $factory->createFromClass($class);
      });
      
  2. Circular Dependencies:

    • Avoid cyclic references in ApiResource operations (e.g., Book referencing Author which references Book).
  3. Namespace Collisions:

    • Use fully qualified attribute names (e.g., ApiPlatform\Metadata\ApiResource) to avoid conflicts.
  4. Deprecation:

    • Some methods (e.g., ResourceFactory::createFromClass()) may change in future API Platform versions. Check upgrading docs.

Debugging Tips

  1. Inspect Descriptions:

    $description = $factory->createFromClass(Book::class);
    dump($description->getAttributes()); // Raw attribute data
    
  2. Validate Operations:

    • Ensure operations (e.g., Get, Post) are properly instantiated and added to ApiResource.
  3. Check for Typos:

    • Attribute names (e.g., normalizationContext vs. serializationContext) are case-sensitive.

Extension Points

  1. Custom Attributes:

    • Create your own attributes by implementing Attribute and extending ResourceFactory:
      #[Attribute]
      class CustomTag {}
      
      class CustomFactory extends ResourceFactory {
          public function createFromClass(string $class): ResourceDescription {
              $description = parent::createFromClass($class);
              foreach ($class::getCustomTags() as $tag) {
                  $description->addAttribute($tag);
              }
              return $description;
          }
      }
      
  2. Override Defaults:

    • Use ResourceDescription::set* methods to modify metadata post-generation:
      $description->setShortName('CustomBookName');
      
  3. Event Listeners:

    • Hook into API Platform’s metadata.event to modify descriptions globally:
      $eventDispatcher->addListener(
          MetadataEvent::class,
          fn(MetadataEvent $event) => $event->getResourceDescription()->addOperation(new AuditOperation())
      );
      

Performance

  • Avoid Redundant Calls: Reuse ResourceFactory instances and cache descriptions.
  • Lazy Loading: Load metadata only when needed (e.g., in controllers):
    $description = $metadataFactory->createFromClass($entityClass);
    
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.
terminal42/code-quality-tools
codifyo/ts-generator-bundle
andydefer/laravel-cluster
testo/fiber
mintobit/jobqueue
a4sex/maintenance-bundle
a4sex/entity-date-update
a4sex/client-identifier
a4sex/base-utilites
a4sex/key-value-storage
a4sex/micro-status
chilldev/dependency-injection-extra
datinglibre/datinglibre-app-api
biberltd/corebundle
bricre/symfony-bundle-test
biberltd/logbundle
dominium/http-adapter-bundle
dominium/google-analytics
a4sex/auto-clean-entity
christhompsontldr/laravel-inky