Installation:
composer require api-platform/metadata
Add to composer.json if using a monorepo or custom package.
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 {}
Key Files:
src/Metadata/ApiResource.php (core class)src/Operation/OperationInterface.php (for CRUD operations)src/Factory/ResourceFactory.php (for dynamic metadata generation)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
@ApiResource, @ApiProperty).
#[ApiProperty(identifier: true)]
private ?int $id = null;
ResourceFactory to generate ResourceDescription objects.ApiResource system or custom logic.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;
}
}
POST operation to all Admin* entities).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']
metadata_dirs to auto-load attributes from files (e.g., Book.yaml).@Assert\NotBlank) and serialization groups.
#[ApiProperty(
groups: ['read', 'write'],
serializationContext: ['groups' => ['read']]
)]
private ?string $title = null;
ResourceDescription in unit tests.
$description = $this->createMock(ResourceDescription::class);
$description->method('getOperations')->willReturn([new Get()]);
Attribute Reflection Overhead:
$cache = new Symfony\Component\Cache\Adapter\FilesystemAdapter();
$description = $cache->get($class, function() use ($factory, $class) {
return $factory->createFromClass($class);
});
Circular Dependencies:
ApiResource operations (e.g., Book referencing Author which references Book).Namespace Collisions:
ApiPlatform\Metadata\ApiResource) to avoid conflicts.Deprecation:
ResourceFactory::createFromClass()) may change in future API Platform versions. Check upgrading docs.Inspect Descriptions:
$description = $factory->createFromClass(Book::class);
dump($description->getAttributes()); // Raw attribute data
Validate Operations:
Get, Post) are properly instantiated and added to ApiResource.Check for Typos:
normalizationContext vs. serializationContext) are case-sensitive.Custom Attributes:
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;
}
}
Override Defaults:
ResourceDescription::set* methods to modify metadata post-generation:
$description->setShortName('CustomBookName');
Event Listeners:
metadata.event to modify descriptions globally:
$eventDispatcher->addListener(
MetadataEvent::class,
fn(MetadataEvent $event) => $event->getResourceDescription()->addOperation(new AuditOperation())
);
ResourceFactory instances and cache descriptions.$description = $metadataFactory->createFromClass($entityClass);
How can I help you explore Laravel packages today?