How to create a Guide

This guide describes every available options to create a guide. Everything is optional and we recommend not to use Doctrine unless the guide is doctrine-specific. We provide a SQLite database, a way to run migrations and fixtures if needed. Usually a guide has a Front Matter header:

slug: how-to
name: How to create a Guide
// When this is true we'll be able to run the guide in
executable: false
position: 0
tags: [doctrine]

Two namespaces are available to register API resources: App\Entity (for Doctrine) and App\ApiResource.

// src/App/Entity.php
namespace App\Entity;
use ApiPlatform\Metadata\ApiResource;
use Doctrine\ORM\Mapping as ORM;
To showcase all the guide possibilities we’re using a Doctrine Entity Book:
class Book
    #[ORM\Id, ORM\Column, ORM\GeneratedValue]
    private ?int $id = null;
    public ?string $title = null;
    public function getId(): ?int
        return $this->id;
We can declare as many namespaces or classes that we need to for this code to work.
// src/App/Service.php
namespace App\Service;
use Psr\Log\LoggerInterface;
class MyService
    public function __construct(private LoggerInterface $logger)
If you need to change something within Symfony’s Container you need to declare this namespace with a configure method.
// src/App/DependencyInjection.php
namespace App\DependencyInjection;
use App\Service\MyService;
use Symfony\Component\DependencyInjection\Loader\Configurator\ContainerConfigurator;
use function Symfony\Component\DependencyInjection\Loader\Configurator\service;
function configure(ContainerConfigurator $configurator): void
    $services = $configurator->services();
Doctrine migrations will run from this namespace.
// src/DoctrineMigrations.php
namespace DoctrineMigrations;
use Doctrine\DBAL\Schema\Schema;
use Doctrine\Migrations\AbstractMigration;
final class Migration extends AbstractMigration
    public function up(Schema $schema): void
And we can load fixtures using Foundry
// src/App/Fixtures.php
namespace App\Fixtures;
use App\Entity\Book;
use Doctrine\Bundle\FixturesBundle\Fixture;
use Doctrine\Persistence\ObjectManager;
use function Zenstruck\Foundry\anonymous;
final class BookFixtures extends Fixture
    public function load(ObjectManager $manager): void
        $bookFactory = anonymous(Book::class);
            'title' => 'title',
The request method is the one executed by the API Platform online Playground on startup.
// src/App/Playground.php
namespace App\Playground;
use Symfony\Component\HttpFoundation\Request;
function request(): Request
    return Request::create('/books.jsonld', 'GET');
The Guide huge advantage is that it is also tested with phpunit.
// src/App/Tests.php
namespace App\Tests;
use ApiPlatform\Playground\Test\TestGuideTrait;
use ApiPlatform\Symfony\Bundle\Test\ApiTestCase;
use App\Entity\Book;
final class BookTest extends ApiTestCase
    use TestGuideTrait;
    public function testAsAnonymousICanAccessTheDocumentation(): void
        $response = static::createClient()->request('GET', '/books.jsonld');
        $this->assertMatchesResourceCollectionJsonSchema(Book::class, '_api_/books{._format}_get_collection', 'jsonld');
        $this->assertNotSame(0, $response->toArray(false)['hydra:totalItems'], 'The collection is empty.');
            'hydra:totalItems' => 10,

You can also help us improve this guide.

Made with love by can help you design and develop your APIs and web projects, and train your teams in API Platform, Symfony, Next.js, Kubernetes and a wide range of other technologies.

Learn more

Copyright © 2023 Kévin Dunglas

Sponsored by