// src/App/Entity.php
namespace App\Entity;
use ApiPlatform\Doctrine\Orm\State\Options;
use ApiPlatform\Doctrine\Orm\Util\QueryNameGeneratorInterface;
use ApiPlatform\Metadata\ApiResource;
use ApiPlatform\Metadata\Get;
use ApiPlatform\Metadata\GetCollection;
use ApiPlatform\Metadata\Link;
use Doctrine\ORM\Mapping as ORM;
use Doctrine\ORM\QueryBuilder;
#[GetCollection(
uriTemplate: '/company/{companyId}/employees',
uriVariables: ['companyId' => new Link(fromClass: Company::class, toProperty: 'company')],
stateOptions: new Options(handleLinks: [Employee::class, 'handleLinks'])
)]
#[Get('/company/{companyId}/employees/{id}')]
#[ORM\Entity]
class Employee
{
#[ORM\Id, ORM\Column, ORM\GeneratedValue]
public ?int $id;
#[ORM\Column]
public string $name;
#[ORM\ManyToOne(targetEntity: Company::class)]
public ?Company $company;
public function getId()
{
return $this->id;
}
public static function handleLinks(QueryBuilder $queryBuilder, array $uriVariables, QueryNameGeneratorInterface $queryNameGenerator, array $context): void
{
$queryBuilder
->andWhere($queryBuilder->getRootAliases()[0].'.company = :companyId')
->setParameter('companyId', $uriVariables['companyId']);
}
}
#[ORM\Entity]
#[ApiResource]
class Company
{
#[ORM\Id, ORM\Column, ORM\GeneratedValue]
public ?int $id;
#[ORM\Column]
public string $name;
}
// src/App/Playground.php
namespace App\Playground;
use Symfony\Component\HttpFoundation\Request;
function request(): Request
{
return Request::create('/company/1/employees', 'GET');
}
// 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
{
$this->addSql('CREATE TABLE company (id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, name VARCHAR(255) NOT NULL);');
$this->addSql('CREATE TABLE employee (id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, company_id INTEGER DEFAULT NULL, name VARCHAR(255) NOT NULL, CONSTRAINT FK_COMPANY FOREIGN KEY (company_id) REFERENCES company (id) NOT DEFERRABLE INITIALLY IMMEDIATE);
$this->addSql('CREATE INDEX FK_COMPANY ON employee (company_id)');
}
}
// src/App/Fixtures.php
namespace App\Fixtures;
use App\Entity\Company;
use App\Entity\Employee;
use Doctrine\Bundle\FixturesBundle\Fixture;
use Doctrine\Persistence\ObjectManager;
use function Zenstruck\Foundry\anonymous;
use function Zenstruck\Foundry\faker;
use function Zenstruck\Foundry\repository;
final class BookFixtures extends Fixture
{
public function load(ObjectManager $manager): void
{
$companyFactory = anonymous(Company::class);
$companyRepository = repository(Company::class);
if ($companyRepository->count()) {
return;
}
$companyFactory->many(1)->create(fn () => [
'name' => faker()->company(),
]);
$employeeFactory = anonymous(Employee::class);
$employeeFactory->many(10)->create(fn () => [
'name' => faker()->name(),
'company' => $companyRepository->first(),
]
);
}
}
Made with love by
Les-Tilleuls.coop 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