### Install API Platform Admin
Source: https://api-platform.com/docs/v3.4/admin/getting-started
Command to install the @api-platform/admin library.
```bash
npm install @api-platform/admin
```
--------------------------------
### Install Schema Generator with Composer
Source: https://api-platform.com/docs/v3.4/schema-generator/getting-started
Installs the Schema Generator independently using Composer.
```bash
composer require --dev api-platform/schema-generator
```
--------------------------------
### YAML Resource Configuration
Source: https://api-platform.com/docs/v3.4/core/getting-started
Example of configuring resources using YAML.
```yaml
resources:
App\Entity\Product: ~
App\Entity\Offer:
shortName: 'Offer' # optional
description: 'An offer from my shop' # optional
types: ['https://schema.org/Offer'] # optional
paginationItemsPerPage: 25 # optional
```
--------------------------------
### XML Resource Configuration
Source: https://api-platform.com/docs/v3.4/core/getting-started
Example of configuring resources using XML.
```xml
description="An offer from my shop"
>
https://schema.org/Offer
```
--------------------------------
### Install GraphQL dependencies
Source: https://api-platform.com/docs/v3.4/distribution
Command to install graphql-php and clear the cache.
```bash
docker compose exec php sh -c '
composer require webonyx/graphql-php
bin/console cache:clear
'
```
--------------------------------
### Install Schema Generator via Docker
Source: https://api-platform.com/docs/v3.4/schema-generator/getting-started
Installs the Schema Generator as a development dependency and invokes it through Docker.
```bash
docker compose exec php \
vendor/bin/schema
```
--------------------------------
### Initialize HydraAdmin
Source: https://api-platform.com/docs/v3.4/admin/getting-started
Example of replacing the content of src/App.js to initialize HydraAdmin with an API entrypoint.
```jsx
import { HydraAdmin } from "@api-platform/admin";
// Replace with your own API entrypoint
// For instance if https://example.com/api/books is the path to the collection of book resources, then the entrypoint is https://example.com/api
export default () => (
);
```
--------------------------------
### Book Resource JSON
Source: https://api-platform.com/docs/v3.4
Example JSON for a new book resource.
```json
{
"description": "This book is designed for PHP developers and architects who want to modernize their skills through better understanding of Persistence and ORM.",
"author": "Kévin Dunglas",
"publicationDate": "2013-12-01"
}
```
--------------------------------
### Install API Platform standalone bundle
Source: https://api-platform.com/docs/v3.4/core/getting-started
Use Composer to install the standalone API Platform bundle in an existing Symfony Flex project.
```bash
composer require api
```
--------------------------------
### Install API Platform's server component
Source: https://api-platform.com/docs/v3.4/distribution
Command to install the API Platform server component using Symfony composer.
```bash
symfony composer require api
```
--------------------------------
### Run Schema Generator with Configuration
Source: https://api-platform.com/docs/v3.4/schema-generator/getting-started
Command to run the schema generator with a configuration file.
```bash
vendor/bin/schema generate api/src/ api/config/schema.yaml -vv
```
--------------------------------
### Start the built-in PHP server
Source: https://api-platform.com/docs/v3.4/distribution
Command to start the built-in PHP server.
```bash
symfony serve
```
--------------------------------
### Generate Code for Specific Resource
Source: https://api-platform.com/docs/v3.4/distribution
Example of generating client code for a specific resource, such as 'books'.
```bash
pnpm create @api-platform/client --resource books
```
--------------------------------
### Create React App
Source: https://api-platform.com/docs/v3.4/admin/getting-started
Command to create a new React application if one does not exist.
```bash
npm init react-app my-admin
cd my-admin
```
--------------------------------
### Enter the project directory
Source: https://api-platform.com/docs/v3.4
This command navigates into the newly created 'bookshop-api' project directory.
```bash
cd bookshop-api
```
--------------------------------
### Cardinality Extraction Usage
Source: https://api-platform.com/docs/v3.4/schema-generator/getting-started
Command to run the Cardinality Extractor tool.
```bash
vendor/bin/schema extract-cardinalities
```
--------------------------------
### Enter the project directory
Source: https://api-platform.com/docs/v3.4/distribution
Command to navigate into the newly created project directory.
```bash
cd bookshop-api
```
--------------------------------
### Create Review Resource
Source: https://api-platform.com/docs/v3.4/distribution
Example JSON payload for creating a new review for a book.
```json
{
"book": "/books/1",
"rating": 5,
"body": "Interesting book!",
"author": "Kévin",
"publicationDate": "September 21, 2016"
}
```
--------------------------------
### Product Entity
Source: https://api-platform.com/docs/v3.4/core/getting-started
Example of an entity mapped using attributes, which will be exposed through a REST API.
```php
offers = new ArrayCollection(); // Initialize $offers as a Doctrine collection
}
public function getId(): ?int
{
return $this->id;
}
// Adding both an adder and a remover as well as updating the reverse relation is mandatory
// if you want Doctrine to automatically update and persist (thanks to the "cascade" option) the related entity
public function addOffer(Offer $offer): void
{
$offer->product = $this;
$this->offers->add($offer);
}
public function removeOffer(Offer $offer): void
{
$offer->product = null;
$this->offers->removeElement($offer);
}
// ...
}
```
--------------------------------
### Create the database and schema
Source: https://api-platform.com/docs/v3.4
These commands create the database and its schema using the Symfony console.
```bash
symfony console doctrine:database:create
symfony console doctrine:schema:create
```
--------------------------------
### GraphQL query for books and reviews
Source: https://api-platform.com/docs/v3.4/distribution
Example GraphQL query to retrieve book data including titles and associated reviews.
```graphql
{
books {
totalCount
edges {
node {
id
title
reviews {
totalCount
edges {
node {
author
rating
}
}
}
}
}
}
}
```
--------------------------------
### GraphQL mutation to create a greeting
Source: https://api-platform.com/docs/v3.4/distribution
Example GraphQL mutation to create a greeting.
```graphql
mutation {
createGreeting(input: {name: "Test2"}) {
greeting {
id
name
}
}
}
```
--------------------------------
### Offer Entity
Source: https://api-platform.com/docs/v3.4/core/getting-started
Example of an Offer entity mapped using attributes, which will be exposed through a REST API.
```php
id;
}
}
```
--------------------------------
### Install API Platform's server component
Source: https://api-platform.com/docs/v3.4
This command installs the API Platform server component into the Symfony skeleton using the Symfony composer.
```bash
symfony composer require api
```
--------------------------------
### POST request body for adding a book
Source: https://api-platform.com/docs/v3.4/distribution
Example JSON body to add a book to the API.
```json
{
"isbn": "2815840053",
"description": "Hello",
"author": "Me",
"publicationDate": "today"
}
```
--------------------------------
### Start the built-in PHP server
Source: https://api-platform.com/docs/v3.4
This command starts the built-in PHP server provided by the Symfony CLI.
```bash
symfony serve
```
--------------------------------
### Example POST Request Body for Book Resource
Source: https://api-platform.com/docs/v3.4/distribution
Example JSON document to be sent as a request body for the POST operation of the Book resource type in Swagger UI.
```json
{
"isbn": "9781782164104",
"title": "Persistence in PHP with the Doctrine ORM",
```
--------------------------------
### Create a new Symfony project
Source: https://api-platform.com/docs/v3.4/distribution
Command to create a new Symfony project.
```bash
symfony new bookshop-api
```
--------------------------------
### Follow Docker Logs
Source: https://api-platform.com/docs/v3.4/distribution
Follows the logs of the Docker containers in real-time.
```bash
docker compose logs -f
```
--------------------------------
### Controller Example
Source: https://api-platform.com/docs/v3.4/core/controllers
This example shows how to define a controller with routes for GET and POST requests.
```PHP
new Get(),
new Post(
name: 'publication',
uriTemplate: '/books/{id}/publication',
controller: CreateBookPublication::class
)
])
class Book
{
// ...
}
```
--------------------------------
### Start Docker Compose
Source: https://api-platform.com/docs/v3.4/distribution
Starts all services defined in the Docker Compose file in detached mode, waiting for services to be ready.
```bash
docker compose up --wait
```
--------------------------------
### Run Schema Generator with Docker and Configuration
Source: https://api-platform.com/docs/v3.4/schema-generator/getting-started
Command to run the schema generator using Docker Compose with a configuration file.
```bash
docker compose exec php \
vendor/bin/schema generate src/ config/schema.yaml -vv
```
--------------------------------
### API Platform Configuration for YAML/XML
Source: https://api-platform.com/docs/v3.4/core/getting-started
Configuration in `api_platform.yaml` to load YAML or XML resource files.
```yaml
# api/config/packages/api_platform.yaml
api_platform:
mapping:
paths:
- '%kernel.project_dir%/src/Entity' # default configuration for attributes
- '%kernel.project_dir%/config/api_platform' # yaml or xml directory configuration
```
--------------------------------
### Schema Configuration for OpenAPI Generation
Source: https://api-platform.com/docs/v3.4/schema-generator/getting-started
A YAML configuration file specifying the path to an OpenAPI documentation file.
```yaml
# api/config/schema.yaml
openApi:
file: '../openapi.yaml'
```
--------------------------------
### Create database and schema
Source: https://api-platform.com/docs/v3.4/distribution
Commands to create the database and its schema using Symfony console.
```bash
symfony console doctrine:database:create
symfony console doctrine:schema:create
```
--------------------------------
### Schema Configuration for Enum Generation
Source: https://api-platform.com/docs/v3.4/schema-generator/getting-started
A YAML configuration file for generating an enum class.
```yaml
types:
OfferItemCondition: # The generator will automatically guess that OfferItemCondition is subclass of Enum
properties: {} # Remove all properties of the parent class
```
--------------------------------
### Generate Database Migrations and Apply
Source: https://api-platform.com/docs/v3.4/distribution
Commands to generate a new database migration and apply it using Doctrine Migrations.
```bash
docker compose exec php \
bin/console doctrine:migrations:diff
docker compose exec php \
bin/console doctrine:migrations:migrate
```
--------------------------------
### Create a new Symfony project
Source: https://api-platform.com/docs/v3.4
This command creates a new Symfony project named 'bookshop-api'.
```bash
symfony new bookshop-api
```
--------------------------------
### Book Entity with Doctrine ORM Attributes
Source: https://api-platform.com/docs/v3.4/distribution
Example of a Book entity mapped to database tables using Doctrine ORM attributes.
```php
use ApiPlatform\Metadata\ApiResource;
use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\ORM\Mapping as ORM;
/** A book. */
#[ORM\Entity]
#[ApiResource]
class Book
{
/** The ID of this book. */
#[ORM\Id, ORM\Column, ORM\GeneratedValue]
private ?int $id = null;
/** The ISBN of this book (or null if doesn't have one). */
#[ORM\Column(nullable: true)]
public ?string $isbn = null;
/** The title of this book. */
#[ORM\Column]
public string $title = '';
/** The description of this book. */
#[ORM\Column(type: 'text')]
public string $description = '';
/** The author of this book. */
#[ORM\Column]
public string $author = '';
/** The publication date of this book. */
#[ORM\Column]
public ?\DateTimeImmutable $publicationDate = null;
/** @var Review[] Available reviews for this book. */
#[ORM\OneToMany(targetEntity: Review::class, mappedBy: 'book', cascade: ['persist', 'remove'])]
public iterable $reviews;
public function __construct()
```
--------------------------------
### NelmioCorsBundle Configuration
Source: https://api-platform.com/docs/v3.4/admin/getting-started
Sample configuration for NelmioCorsBundle to expose the Link HTTP header and send proper CORS headers.
```yaml
# config/packages/nelmio_cors.yaml
nelmio_cors:
paths:
'^/api/':
origin_regex: true
allow_origin: ['^http://localhost:[0-9]+'] # You probably want to change this regex to match your real domain
allow_methods: ['GET', 'OPTIONS', 'POST', 'PUT', 'PATCH', 'DELETE']
allow_headers: ['Content-Type', 'Authorization']
expose_headers: ['Link']
max_age: 3600
```
--------------------------------
### Start Docker Compose with Custom Configuration
Source: https://api-platform.com/docs/v3.4/distribution
Starts the web server on port 8080 with HTTPS disabled, overriding default server name and trusted hosts.
```bash
SERVER_NAME=localhost:80 HTTP_PORT=8080 TRUSTED_HOSTS=localhost docker compose up --wait
```
--------------------------------
### Clear Cache
Source: https://api-platform.com/docs/v3.4/admin/getting-started
Command to clear the cache to apply NelmioCorsBundle configuration changes.
```bash
docker compose exec php \
bin/console cache:clear --env=prod
```
--------------------------------
### Schema Configuration for Model Scaffolding
Source: https://api-platform.com/docs/v3.4/schema-generator/getting-started
A YAML configuration file for generating data models for an address book using Schema.org types.
```yaml
# api/config/schema.yaml
# The list of types and properties we want to use
types:
# Parent class of Person
Thing:
properties:
name: ~
Person:
# Enable the generation of the class hierarchy (not enabled by default)
parent: ~
properties:
familyName: ~
givenName: ~
additionalName: ~
address: ~
PostalAddress:
properties:
# Force the type of the addressCountry property to text
addressCountry: { range: "Text" }
addressLocality: ~
addressRegion: ~
postOfficeBoxNumber: ~
postalCode: ~
streetAddress: ~
```
--------------------------------
### Build Docker Images
Source: https://api-platform.com/docs/v3.4/distribution
Builds the Docker images for the API Platform services without using the cache.
```bash
docker compose build --no-cache
```
--------------------------------
### API Platform v3.4 Bootstrap Example
Source: https://api-platform.com/docs/v3.4/core/bootstrap
This code snippet illustrates the setup of various actions, factories, and routes for API Platform v3.4, culminating in the handling of an HTTP request.
```php
$paginationOptions = new PaginationOptions();
$openApiOptions = new OpenApiOptions('API Platform');
$jsonSchemaTypeFactory = new TypeFactory($resourceClassResolver);
$jsonSchemaFactory = new SchemaFactory($jsonSchemaTypeFactory, $resourceMetadataFactory, $propertyNameCollectionFactory, $propertyMetadataFactory, $nameConverter, $resourceClassResolver);
$openApiFactory = new OpenApiFactory($resourceNameCollectionFactory, $resourceMetadataFactory, $propertyNameCollectionFactory, $propertyMetadataFactory, $jsonSchemaFactory, $jsonSchemaTypeFactory, $filterLocator);
$documentationAction = new DocumentationAction($openApiFactory);
$routes->add('api_doc', new Route('/docs.{_format}', ['_controller' => $documentationAction, '_format' => null, '_api_respond' => true]));
$entryPointAction = new EntrypointAction($resourceNameCollectionFactory);
$routes->add('api_entrypoint', new Route('/{index}.{_format}', ['_controller' => $entryPointAction, '_format' => null, '_api_respond' => true, 'index' => 'index'], ['index' => 'index']));
$contextAction = new ContextAction($jsonLdContextBuilder, $resourceNameCollectionFactory, $resourceMetadataFactory);
$routes->add('api_jsonld_context', new Route('/contexts/{shortName}.{_format}', ['_controller' => $contextAction, '_format' => 'jsonld', '_api_respond' => true], ['shortName' => '.+']));
$notExposedAction = new NotExposedAction();
$routes->add('api_genid', new Route('/.well-known/genid/{id}', ['_controller' => $notExposedAction, '_format' => 'text', '_api_respond' => true]));
$controllerResolver = new ControllerResolver();
$argumentResolver = new ArgumentResolver();
$kernel = new HttpKernel($dispatcher, $controllerResolver, new RequestStack(), $argumentResolver);
$request = Request::createFromGlobals();
$response = $kernel->handle($request);
$response->send();
$kernel->terminate($request, $response);
```
--------------------------------
### Bootstrap Next.js App
Source: https://api-platform.com/docs/v3.4/distribution
Command to bootstrap a Next.js app using API Platform's client generator.
```bash
docker compose exec pwa \
pnpm create @api-platform/client
```
--------------------------------
### Provider and Processor Collection Setup
Source: https://api-platform.com/docs/v3.4/core/bootstrap
Illustrates the creation of container-like objects for state providers and state processors, using anonymous classes implementing ContainerInterface.
```php
$providerCollection = new class implements ContainerInterface {
public array $providers = [];
public function get($id) {
return $this->providers[$id];
}
public function has($id): bool {
return isset($this->providers[$id]);
}
};
$stateProviders = new CallableProvider($providerCollection);
$processorCollection = new class implements ContainerInterface {
public array $processors = [];
public function get($id) {
return $this->processors[$id];
}
public function has($id): bool {
return isset($this->processors['id']);
}
};
$stateProcessors = new CallableProcessor($processorCollection);
```
--------------------------------
### GraphQL query to read a greeting
Source: https://api-platform.com/docs/v3.4/distribution
Example GraphQL query to read a greeting by its ID.
```graphql
{
greeting(id: "/greetings/1") {
id
name
_id
}
}
```
--------------------------------
### Initial YAML Configuration Example
Source: https://api-platform.com/docs/v3.4/core/security
An initial example showing security configuration for a Book resource in YAML, including a specific rule for PUT operations.
```yaml
resources:
App\Entity\Book:
operations:
ApiPlatform\Metadata\Get: ~
ApiPlatform\Metadata\GetCollectionPut:
securityPostDenormalize: "is_granted('ROLE_ADMIN') or (object.owner == user and previous_object.owner == user)"
# ...
```
--------------------------------
### Start Minikube Cluster
Source: https://api-platform.com/docs/v3.4/deployment/minikube
Starts Minikube with a Docker registry and the Kubernetes dashboard enabled.
```bash
minikube start --addons registry --addons dashboard
```
--------------------------------
### Validation Error Response
Source: https://api-platform.com/docs/v3.4/distribution
Example JSON response showing validation errors in Hydra format.
```json
{
"@context": "/contexts/ConstraintViolationList",
"@type": "ConstraintViolationList",
"hydra:title": "An error occurred",
"hydra:description": "isbn: This value is neither a valid ISBN-10 nor a valid ISBN-13.\ntitle: This value should not be blank.",
"violations": [
{
"propertyPath": "isbn",
"message": "This value is neither a valid ISBN-10 nor a valid ISBN-13."
},
{
"propertyPath": "title",
"message": "This value should not be blank."
}
]
}
```
--------------------------------
### Review Entity with Doctrine ORM Attributes
Source: https://api-platform.com/docs/v3.4
Example of a Review entity mapped to database tables using Doctrine ORM attributes.
```php
namespace App\Entity;
use ApiPlatform\Metadata\ApiResource;
use Doctrine\ORM\Mapping as ORM;
/** A review of a book. */
#[ORM\Entity]
#[ApiResource]
class Review
{
/** The ID of this review. */
#[ORM\Id, ORM\Column, ORM\GeneratedValue]
private ?int $id = null;
/** The rating of this review (between 0 and 5). */
#[ORM\Column(type: 'smallint')]
public int $rating = 0;
/** The body of the review. */
#[ORM\Column(type: 'text')]
public string $body = '';
/** The author of the review. */
#[ORM\Column]
public string $author = '';
/** The date of publication of this review. */
#[ORM\Column]
public ?\DateTimeImmutable $publicationDate = null;
/** The book this review is about. */
#[ORM\ManyToOne(inversedBy: 'reviews')]
public ?Book $book = null;
public function getId(): ?int
```
--------------------------------
### Review Entity with Doctrine ORM Attributes
Source: https://api-platform.com/docs/v3.4/distribution
Example of a Review entity mapped to database tables using Doctrine ORM attributes.
```php
namespace App\Entity;
use ApiPlatform\Metadata\ApiResource;
use Doctrine\ORM\Mapping as ORM;
/** A review of a book. */
#[ORM\Entity]
#[ApiResource]
class Review
{
/** The ID of this review. */
#[ORM\Id, ORM\Column, ORM\GeneratedValue]
private ?int $id = null;
/** The rating of this review (between 0 and 5). */
#[ORM\Column(type: 'smallint')]
public int $rating = 0;
/** The body of the review. */
#[ORM\Column(type: 'text')]
public string $body = '';
/** The author of the review. */
#[ORM\Column]
public string $author = '';
/** The date of publication of this review. */
#[ORM\Column]
public ?\DateTimeImmutable $publicationDate = null;
/** The book this review is about. */
#[ORM\ManyToOne(inversedBy: 'reviews')]
public ?Book $book = null;
public function getId(): ?int
```
--------------------------------
### Start Skaffold in Dev Mode
Source: https://api-platform.com/docs/v3.4/deployment/minikube
Starts Skaffold in development mode from the helm directory for continuous deployment.
```bash
cd ./helm
skaffold dev
```
--------------------------------
### Service Instantiation Example
Source: https://api-platform.com/docs/v3.4/core/bootstrap
This snippet demonstrates the instantiation and configuration of various normalizers and services used in the API Platform core bootstrap process. It includes examples for Hydra, HAL, JSON-LD, and general object normalization.
```php
/**new UriVariablesConverter($propertyMetadataFactory, $resourceMetadataFactory, $uriVariableTransformers)*/ null,
);
$serializerContextBuilder = new SerializerContextBuilder($resourceMetadataFactory);
$objectNormalizer = new ObjectNormalizer();
$nameConverter = new MetadataAwareNameConverter($classMetadataFactory);
$jsonLdContextBuilder = new JsonLdContextBuilder($resourceNameCollectionFactory, $resourceMetadataFactory, $propertyNameCollectionFactory, $propertyMetadataFactory, $apiUrlGenerator, $iriConverter, $nameConverter);
$jsonLdItemNormalizer = new JsonLdItemNormalizer($resourceMetadataFactory, $propertyNameCollectionFactory, $propertyMetadataFactory, $iriConverter, $resourceClassResolver, $jsonLdContextBuilder, $propertyAccessor, $nameConverter, $classMetadataFactory, $defaultContext, /** resource access checker **/ null);
$jsonLdObjectNormalizer = new JsonLdObjectNormalizer($objectNormalizer, $iriConverter, $jsonLdContextBuilder);
$jsonLdEncoder = new JsonLdEncoder('jsonld', new JsonEncoder());
$problemConstraintViolationListNormalizer = new ProblemConstraintViolationListNormalizer([], $nameConverter, $defaultContext);
$hydraCollectionNormalizer = new HydraCollectionNormalizer($jsonLdContextBuilder, $resourceClassResolver, $iriConverter, $resourceMetadataFactory, $defaultContext);
$hydraPartialCollectionNormalizer = new PartialCollectionViewNormalizer($hydraCollectionNormalizer, $configuration['collection']['pagination']['page_parameter_name'], $configuration['collection']['pagination']['enabled_parameter_name'], $resourceMetadataFactory, $propertyAccessor);
$hydraCollectionFiltersNormalizer = new CollectionFiltersNormalizer($hydraPartialCollectionNormalizer, $resourceMetadataFactory, $resourceClassResolver, $filterLocator);
$hydraErrorNormalizer = new HydraErrorNormalizer($apiUrlGenerator, $debug, $defaultContext);
$hydraEntrypointNormalizer = new HydraEntrypointNormalizer($resourceMetadataFactory, $iriConverter, $apiUrlGenerator);
$hydraDocumentationNormalizer = new HydraDocumentationNormalizer($resourceMetadataFactory, $propertyNameCollectionFactory, $propertyMetadataFactory, $resourceClassResolver, $apiUrlGenerator, $nameConverter);
$hydraConstraintViolationNormalizer = new HydraConstraintViolationListNormalizer($apiUrlGenerator, [], $nameConverter);
$problemErrorNormalizer = new ErrorNormalizer($debug, $defaultContext);
// $expressionLanguage = new ExpressionLanguage();
// $resourceAccessChecker = new ResourceAccessChecker(
// $expressionLanguage,
// );
$itemNormalizer = new ItemNormalizer(
$propertyNameCollectionFactory,
$propertyMetadataFactory,
$iriConverter,
$resourceClassResolver,
$propertyAccessor,
$nameConverter,
$classMetadataFactory,
$logger,
$resourceMetadataFactory,
/**$resourceAccessChecker **/ null,
$defaultContext
);
$arrayDenormalizer = new ArrayDenormalizer();
$problemNormalizer = new ProblemNormalizer($debug, $defaultContext);
$jsonserializableNormalizer = new JsonSerializableNormalizer($classMetadataFactory, $nameConverter, $defaultContext);
$dateTimeNormalizer = new DateTimeNormalizer($defaultContext);
$dataUriNormalizer = new DataUriNormalizer();
$dateIntervalNormalizer = new DateIntervalNormalizer($defaultContext);
$dateTimeZoneNormalizer = new DateTimeZoneNormalizer();
$constraintViolationListNormalizer = new ConstraintViolationListNormalizer($defaultContext, $nameConverter);
$unwrappingDenormalizer = new UnwrappingDenormalizer($propertyAccessor);
$halItemNormalizer = new HalItemNormalizer($propertyNameCollectionFactory, $propertyMetadataFactory, $iriConverter, $resourceClassResolver, $propertyAccessor, $nameConverter, $classMetadataFactory, $defaultContext, $resourceMetadataFactory, /** resourceAccessChecker **/ null);
$halItemNormalizer = new HalItemNormalizer($propertyNameCollectionFactory, $propertyMetadataFactory, $iriConverter, $resourceClassResolver, $propertyAccessor, $nameConverter, $classMetadataFactory, $defaultContext, $resourceMetadataFactory, /** resourceAccessChecker **/ null);
$halEntrypointNormalizer = new HalEntrypointNormalizer($resourceMetadataFactory, $iriConverter, $apiUrlGenerator);
$halCollectionNormalizer = new HalCollectionNormalizer($resourceClassResolver, $configuration['collection']['pagination']['page_parameter_name'], $resourceMetadataFactory);
$halObjectNormalizer = new HalObjectNormalizer($objectNormalizer, $iriConverter);
$openApiNormalizer = new OpenApiNormalizer($objectNormalizer);
$list = new \SplPriorityQueue();
$list->insert($unwrappingDenormalizer, 1000);
$list->insert($halItemNormalizer, -890);
$list->insert($hydraConstraintViolationNormalizer, -780);
$list->insert($hydraEntrypointNormalizer, -800);
$list->insert($hydraErrorNormalizer, -800);
$list->insert($hydraCollectionFiltersNormalizer, -800);
$list->insert($halEntrypointNormalizer, -800);
$list->insert($halCollectionNormalizer, -985);
$list->insert($halObjectNormalizer, -995);
```
--------------------------------
### Example Functional Test: Get Collection
Source: https://api-platform.com/docs/v3.4/distribution/testing
An example of a functional test for retrieving a collection of books.
```php
request('GET', '/books');
$this->assertResponseIsSuccessful();
// Asserts that the returned content type is JSON-LD (the default)
$this->assertResponseHeaderSame('content-type', 'application/ld+json; charset=utf-8');
// Asserts that the returned JSON is a superset of this one
$this->assertJsonContains([
'@context' => '/contexts/Book',
'@id' => '/books',
'@type' => 'hydra:Collection',
'hydra:totalItems' => 100,
'hydra:view' => [
'@id' => '/books?page=1',
'@type' => 'hydra:PartialCollectionView',
'hydra:first' => '/books?page=1',
'hydra:last' => '/books?page=4',
'hydra:next' => '/books?page=2',
],
]);
// Because test fixtures are automatically loaded between each test, you can assert on them
$this->assertCount(30, $response->toArray()['hydra:member']);
// Asserts that the returned JSON is validated by the JSON Schema generated for this resource by API Platform
// This generated JSON Schema is also used in the OpenAPI spec!
$this->assertMatchesResourceCollectionJsonSchema(Book::class);
}
public function testCreateBook(): void
{
$response = static::createClient()->request('POST', '/books', ['json' => [
'isbn' => '0099740915',
'title' => 'The Handmaid\'s Tale',
'description' => 'Brilliantly conceived and executed, this powerful evocation of twenty-first century America gives full rein to Margaret Atwood\'s devastating irony, wit and astute perception.',
'author' => 'Margaret Atwood',
'publicationDate' => '1985-07-31T00:00:00+00:00',
]]);
$this->assertResponseStatusCodeSame(201);
$this->assertResponseHeaderSame('content-type', 'application/ld+json; charset=utf-8');
$this->assertJsonContains([
'@context' => '/contexts/Book',
'@type' => 'Book',
'isbn' => '0099740915',
'title' => 'The Handmaid\'s Tale',
'description' => 'Brilliantly conceived and executed, this powerful evocation of twenty-first century America gives full rein to Margaret Atwood\'s devastating irony, wit and astute perception.',
'author' => 'Margaret Atwood',
'publicationDate' => '1985-07-31T00:00:00+00:00',
'reviews' => [],
]);
$this->assertMatchesRegularExpression('~^/books/\d+$~', $response->toArray()['@id']);
$this->assertMatchesResourceItemJsonSchema(Book::class);
}
public function testCreateInvalidBook(): void
{
static::createClient()->request('POST', '/books', ['json' => [
'isbn' => 'invalid',
]]);
$this->assertResponseStatusCodeSame(422);
```
--------------------------------
### Bring up the full project
Source: https://api-platform.com/docs/v3.4/deployment/docker-compose
Command to bring up the entire project after building the 'pwa' service.
```bash
SERVER_NAME=http://localhost \
MERCURE_PUBLIC_URL=http://localhost/.well-known/mercure \
TRUSTED_HOSTS='^localhost|php$' \
APP_SECRET=!ChangeMe! \
CADDY_MERCURE_JWT_SECRET=ChangeThisMercureHubJWTSecretKey \
POSTGRES_PASSWORD=!ChangeMe! \
docker compose -f compose.yaml -f compose.prod.yaml up -d --wait
```
--------------------------------
### Install Google Cloud SDK
Source: https://api-platform.com/docs/v3.4/deployment/kubernetes
Command to download and install the Google Cloud SDK.
```bash
curl https://sdk.cloud.google.com | bash
```
--------------------------------
### Build Docker Images
Source: https://api-platform.com/docs/v3.4/deployment/minikube
Builds the necessary Docker images for the API Platform components.
```bash
docker build -t localhost:5000/php api --target api_platform_php
docker build -t localhost:5000/caddy api --target api_platform_caddy
docker build -t localhost:5000/pwa pwa --target api_platform_pwa_prod
```
--------------------------------
### Caddyfile Routing Rule
Source: https://api-platform.com/docs/v3.4/distribution/caddy
Example of modifying the Caddyfile to route requests starting with /admin to the API.
```caddyfile
# Matches requests for HTML documents, for static files and for Next.js files,
# except for known API paths and paths with extensions handled by API Platform
@pwa expression `(
{header.Accept}.matches("\\btext/html\\b")
&& !{path}.matches("(?i)(?:^/docs|^/graphql|^/bundles/|^/_profiler|^/_wdt|\\.(?:json|html$|csv$|ya?ml$|xml$))")
&& !{path}.matches("(?i)(?:^/admin|^/docs|^/graphql|^/bundles/|^/_profiler|^/_wdt|\\.(?:json|html$|csv$|ya?ml$|xml$))")
)`
```
--------------------------------
### Review Entity
Source: https://api-platform.com/docs/v3.4/distribution
Defines the Review resource type with its properties and the #[ApiResource] attribute.
```php
id;
}
}
```
--------------------------------
### Install Foundry and Doctrine/DoctrineFixturesBundle
Source: https://api-platform.com/docs/v3.4/distribution/testing
Installs the necessary packages for creating data fixtures.
```bash
docker compose exec php \
composer require --dev foundry orm-fixtures
```
--------------------------------
### Book Entity
Source: https://api-platform.com/docs/v3.4/distribution
Defines the Book resource type with its properties and the #[ApiResource] attribute.
```php
reviews = new ArrayCollection();
}
public function getId(): ?int
{
return $this->id;
}
}
```
--------------------------------
### Start the development server
Source: https://api-platform.com/docs/v3.4/create-client/react
Start the integrated web server to view the application.
```bash
npm run dev
```
--------------------------------
### Explicitly Handling JSON Format
Source: https://api-platform.com/docs/v3.4/core/upgrade-guide
Example of explicitly handling the 'json' format when it's not enabled by default.
```yaml
formats:
json: ['application/json']
```
--------------------------------
### Composer.json Update for Standalone Packages
Source: https://api-platform.com/docs/v3.4/core/upgrade-guide
Example of updating composer.json to use standalone API Platform packages.
```json
{
"require": {
"api-platform/core": "^3",
"api-platform/symfony": "^3 || ^4"
// also add the extra packages you need, like "api-platform/doctrine-orm"
}
}
```
--------------------------------
### Install VichUploaderBundle
Source: https://api-platform.com/docs/v3.4/core/file-upload
Installs the VichUploaderBundle using Composer.
```bash
docker compose exec php \
composer require vich/uploader-bundle
```
--------------------------------
### Build and start the php service
Source: https://api-platform.com/docs/v3.4/deployment/docker-compose
Command to build and start the php service container with specific environment variables.
```bash
SERVER_NAME=http://localhost \
MERCURE_PUBLIC_URL=http://localhost/.well-known/mercure \
TRUSTED_HOSTS='^localhost|php$' \
APP_SECRET=!ChangeMe! \
CADDY_MERCURE_JWT_SECRET=ChangeThisMercureHubJWTSecretKey \
POSTGRES_PASSWORD=!ChangeMe! \
docker compose -f compose.yaml -f compose.prod.yaml up -d --build --wait php
```
--------------------------------
### Review Entity with Validation Constraints
Source: https://api-platform.com/docs/v3.4/distribution
PHP code showing the Review entity with added validation constraints.
```php
use ApiPlatform\Metadata\ApiResource;
use Doctrine\ORM\Mapping as ORM;
use Symfony\Component\Validator\Constraints as Assert;
#[ORM\Column(type: 'smallint')]
#[Assert\Range(min: 0, max: 5)]
public int $rating = 0;
#[ORM\Column(type: 'text')]
#[Assert\NotBlank]
public string $body = '';
#[ORM\Column]
#[Assert\NotBlank]
public string $author = '';
#[ORM\Column]
#[Assert\NotNull]
public ?\DateTimeImmutable $publicationDate = null;
#[ORM\ManyToOne(inversedBy: 'reviews')]
#[Assert\NotNull]
public ?Book $book = null;
public function getId(): ?int
```
--------------------------------
### Install DAMADoctrineTestBundle
Source: https://api-platform.com/docs/v3.4/distribution/testing
Install the DAMADoctrineTestBundle to automatically reset the database before each test.
```bash
docker compose exec php \
composer require --dev dama/doctrine-test-bundle
```
--------------------------------
### Setting Custom HTTP Cache Headers Per Operation
Source: https://api-platform.com/docs/v3.4/core/performance
Example of setting different cache headers for a specific operation (GET) on a resource.
```php
use ApiPlatform\Metadata\ApiResource;
use ApiPlatform\Metadata\Get;
#[ApiResource]
#[Get(
cacheHeaders: [
'max_age' => 60,
'shared_max_age' => 120,
]
)]
class Book
{
// ...
}
```
--------------------------------
### Example .env file
Source: https://api-platform.com/docs/v3.4/deployment/traefik
An example of an environment file to define necessary variables for the deployment.
```env
CONTAINER_REGISTRY_BASE=quay.io/api-platform
DOMAIN_NAME=localhost
HTTP_OR_SSL=https://
DB_NAME=api-platform-db-name
DB_PASS=YouMustChangeThisPassword
DB_USER=api-platform
JWT_KEY=!UnsecureChangeMe!
SUBDOMAINS_LIST=(admin|api|mercure)
```
--------------------------------
### Clone your project repository
Source: https://api-platform.com/docs/v3.4/deployment/docker-compose
Copy your project files to the server using Git. Replace and with your actual GitHub details.
```bash
git clone git@github.com:/.git
```