2026年版 API Platform と Symfony: アーキテクチャ設計と技術面接対策ガイド
API Platform 4.2とSymfony 7.4を活用したREST API開発の最新手法を解説。State Provider、State Processor、Object Mapper、JSON Streamerによる32%のパフォーマンス向上まで、技術面接で問われる重要概念を網羅します。

API Platform 4.2は、SymfonyアプリケーションがREST APIとGraphQL APIを公開する方法を根本から変革しています。このバージョンでは、リソース分離を実現するSymfony Object Mapper、大幅なパフォーマンス向上をもたらすJSON Streamer、そして再設計されたフィルターシステムが導入されました。技術面接に臨む開発者にとって、これらのアーキテクチャパターンを理解することは、シニアとジュニアを分ける重要な要素となります。
API Platform 4.2はSymfony 7.4または8.0を必要とします。Symfony 6.4および7.0〜7.3のサポートは終了しました。JSON Streamerはコレクションエンドポイントで最大32%のリクエスト処理能力向上を実現します。
API Platform 4.2とSymfonyのセットアップ
API PlatformはSymfony Flexを通じて自動設定でインストールされます。デフォルトのセットアップはほとんどのユースケースに対応しつつ、複雑なドメイン要件に対しては完全にカスタマイズ可能です。
# Install API Platform
composer require api-platform/symfony
# The API documentation is available at /api/
# Open http://localhost:8000/api/ after starting the server
symfony serveFlexレシピは、シリアライゼーショングループ、Doctrine統合、OpenAPIドキュメント生成を自動的に設定します。APIリソースは、エンティティクラスに単一のアトリビュートを追加するだけでCRUD操作を公開できます。
namespace App\Entity;
use ApiPlatform\Metadata\ApiResource;
use ApiPlatform\Metadata\Get;
use ApiPlatform\Metadata\GetCollection;
use ApiPlatform\Metadata\Post;
use ApiPlatform\Metadata\Put;
use ApiPlatform\Metadata\Delete;
use Doctrine\ORM\Mapping as ORM;
use Symfony\Component\Validator\Constraints as Assert;
#[ORM\Entity]
#[ApiResource(
operations: [
new GetCollection(),
new Get(),
new Post(security: "is_granted('ROLE_ADMIN')"),
new Put(security: "is_granted('ROLE_ADMIN')"),
new Delete(security: "is_granted('ROLE_ADMIN')")
],
normalizationContext: ['groups' => ['book:read']],
denormalizationContext: ['groups' => ['book:write']]
)]
class Book
{
#[ORM\Id]
#[ORM\GeneratedValue]
#[ORM\Column]
private ?int $id = null;
#[ORM\Column(length: 255)]
#[Assert\NotBlank]
#[Groups(['book:read', 'book:write'])]
private string $title;
#[ORM\Column(type: 'text')]
#[Groups(['book:read', 'book:write'])]
private string $description;
#[ORM\Column]
#[Groups(['book:read'])]
private \DateTimeImmutable $createdAt;
// Getters and setters...
}この設定により、自動バリデーション、シリアライゼーション、OpenAPIドキュメントを備えた5つのエンドポイントが生成されます。
State Provider: 任意のデータソースからのデータ取得
State Providerは、API PlatformがGET操作でデータを取得する方法を制御します。デフォルトのDoctrine Providerはエンティティの取得を処理しますが、カスタムProviderを使用することで、外部API、Elasticsearch、またはキャッシュデータとの統合が可能になります。
namespace App\State;
use ApiPlatform\Metadata\Operation;
use ApiPlatform\State\ProviderInterface;
use App\Repository\BookRepository;
use Psr\Cache\CacheItemPoolInterface;
final class BookStateProvider implements ProviderInterface
{
public function __construct(
private BookRepository $repository,
private CacheItemPoolInterface $cache
) {}
public function provide(Operation $operation, array $uriVariables = [], array $context = []): object|array|null
{
// Single item retrieval
if (isset($uriVariables['id'])) {
$cacheKey = sprintf('book_%d', $uriVariables['id']);
$item = $this->cache->getItem($cacheKey);
if ($item->isHit()) {
return $item->get();
}
$book = $this->repository->find($uriVariables['id']);
$item->set($book)->expiresAfter(3600);
$this->cache->save($item);
return $book;
}
// Collection retrieval with custom filtering
return $this->repository->findActiveBooks();
}
}特定のオペレーションにProviderを登録する方法は以下の通りです。
#[ApiResource(
operations: [
new GetCollection(provider: BookStateProvider::class),
new Get(provider: BookStateProvider::class),
// Other operations use default Doctrine provider
new Post(),
new Put(),
]
)]
class Book { /* ... */ }State Processor: ビジネスロジックを含むミューテーション処理
State Processorは、POST、PUT、PATCH、DELETE操作を処理します。デシリアライズされたデータを受け取り、永続化の前にビジネスロジックを適用します。
namespace App\State;
use ApiPlatform\Metadata\Operation;
use ApiPlatform\State\ProcessorInterface;
use App\Entity\Book;
use Doctrine\ORM\EntityManagerInterface;
use Symfony\Component\Mailer\MailerInterface;
use Symfony\Component\Mime\Email;
final class BookStateProcessor implements ProcessorInterface
{
public function __construct(
private EntityManagerInterface $em,
private MailerInterface $mailer,
private ProcessorInterface $persistProcessor // Decorated Doctrine processor
) {}
public function process(
mixed $data,
Operation $operation,
array $uriVariables = [],
array $context = []
): mixed {
// Pre-persist business logic
if ($data instanceof Book && $operation instanceof Post) {
$data->setCreatedAt(new \DateTimeImmutable());
$data->setSlug($this->generateSlug($data->getTitle()));
}
// Delegate to Doctrine processor
$result = $this->persistProcessor->process($data, $operation, $uriVariables, $context);
// Post-persist notification
if ($operation instanceof Post) {
$this->notifyNewBook($data);
}
return $result;
}
private function generateSlug(string $title): string
{
return strtolower(preg_replace('/[^a-zA-Z0-9]+/', '-', $title));
}
private function notifyNewBook(Book $book): void
{
$email = (new Email())
->to('catalog@example.com')
->subject('New book added: ' . $book->getTitle())
->text('A new book has been added to the catalog.');
$this->mailer->send($email);
}
}デフォルトのDoctrine Processorを#[AsDecorator]でデコレートすることで、永続化の動作を維持しながらカスタムロジックを追加できます。このパターンにより、ORM操作の重複を避けることができます。
Object Mapper: APIリソースとエンティティの分離
API Platform 4.2は、Symfony Object Mapperコンポーネントを統合し、API表現をドメインエンティティから分離します。この分離により、異なる読み取り/書き込みモデルが可能になり、内部エンティティ構造を保護できます。
namespace App\ApiResource;
use ApiPlatform\Metadata\ApiResource;
use ApiPlatform\Metadata\Get;
use ApiPlatform\Metadata\GetCollection;
use App\Entity\Book;
use Symfony\Component\ObjectMapper\Attribute\Map;
#[ApiResource(
shortName: 'Book',
operations: [
new GetCollection(),
new Get()
]
)]
#[Map(target: Book::class)]
class BookResource
{
public ?int $id = null;
public string $title;
public string $description;
// Computed field not in entity
public int $wordCount;
// Formatted date for API consumers
public string $publishedDate;
}Mapperプロバイダーはエンティティをリソースに自動的に変換します。
namespace App\State;
use ApiPlatform\Metadata\Operation;
use ApiPlatform\State\ProviderInterface;
use App\ApiResource\BookResource;
use App\Repository\BookRepository;
use Symfony\Component\ObjectMapper\ObjectMapperInterface;
final class BookResourceProvider implements ProviderInterface
{
public function __construct(
private BookRepository $repository,
private ObjectMapperInterface $mapper
) {}
public function provide(Operation $operation, array $uriVariables = [], array $context = []): object|array|null
{
if (isset($uriVariables['id'])) {
$book = $this->repository->find($uriVariables['id']);
return $book ? $this->toResource($book) : null;
}
return array_map(
fn(Book $book) => $this->toResource($book),
$this->repository->findAll()
);
}
private function toResource(Book $book): BookResource
{
$resource = $this->mapper->map($book, BookResource::class);
$resource->wordCount = str_word_count($book->getDescription());
$resource->publishedDate = $book->getCreatedAt()->format('F j, Y');
return $resource;
}
}Symfonyの面接対策はできていますか?
インタラクティブなシミュレーター、flashcards、技術テストで練習しましょう。
JSON Streamer: 32%のパフォーマンス向上
JSON Streamerコンポーネントは、データセット全体をメモリにロードせずに大規模なコレクションをシリアライズします。Sylius APIでのベンチマークでは、1秒あたりのリクエスト数が32.4%増加しました。
リソースまたはオペレーションレベルでストリーミングを有効にする方法は以下の通りです。
#[ApiResource(
operations: [
new GetCollection(
jsonStream: true, // Enable JSON streaming
paginationItemsPerPage: 100
),
new Get()
]
)]
class Book { /* ... */ }ストリーミングが特に効果的な場面は以下の通りです。
- 50件以上のアイテムを含むコレクションエンドポイント
- ネストされたリレーションシップを持つリソース
- 帯域幅が限られたモバイルクライアントへのAPI提供
OpenAPI仕様も最適化されました。JSON Schemaの共通化により、ファイルサイズが30%削減され、ドキュメントの読み込み時間が改善されました。
技術面接: API Platformアーキテクチャに関する質問
Symfonyポジションの技術面接では、API Platformのパターンが頻繁に取り上げられます。これらの質問は、基本的なCRUD操作を超えたフレームワークのアーキテクチャ理解を評価します。
「State ProviderとProcessorの違いを説明してください」
期待される回答: State Providerは読み取り操作(GET)のデータ取得を処理します。エンティティ、DTO、または配列を返します。State Processorは書き込み操作(POST、PUT、PATCH、DELETE)を処理します。デシリアライズされた入力を受け取り、永続化の前にビジネスロジックを実行します。この分離はCQRS原則に従っています:クエリはProviderを通じて、コマンドはProcessorを通じて処理されます。
「エンティティを直接公開する代わりに、カスタムAPIリソースを使用するのはどのような場合ですか?」
期待される回答: カスタムリソースは以下の場合に適用されます。
- API表現がデータベーススキーマと異なる場合
- 計算フィールドが複数のエンティティからの集計を必要とする場合
- 書き込みモデルと読み取りモデルで異なる構造が必要な場合
- 内部エンティティフィールドをAPIコンシューマーから隠す必要がある場合
- エンティティが進化する一方で、バージョン互換性のために安定した契約が必要な場合
「API Platformはバリデーションをどのように処理しますか?」
期待される回答: API Platformは、エンティティプロパティのSymfony Validatorコンストレイントを使用します。バリデーションは、State Processorが実行される前のデシリアライゼーション中に自動的に実行されます。バリデーショングループは、オペレーションごとに適用されるコンストレイントを制御します。カスタムバリデーターは標準的なSymfonyメカニズムを通じて統合されます。
#[ApiResource(
operations: [
new Post(validationContext: ['groups' => ['create']]),
new Put(validationContext: ['groups' => ['update']])
]
)]
class Book
{
#[Assert\NotBlank(groups: ['create', 'update'])]
private string $title;
#[Assert\Isbn(groups: ['create'])]
private string $isbn; // Required only on creation
}候補者は、バリデーショングループやカスタムコンストレイントに言及せずに、バリデーションを「自動」と説明することがよくあります。面接官は、オペレーションごとにバリデーションをカスタマイズする方法の理解を確認しています。
「API Platformが提供するセキュリティメカニズムは何ですか?」
期待される回答: API Platformは以下を通じてSymfony Securityと統合します。
- ロールベースアクセス用のオペレーションの
security属性 - データバインディング後のオブジェクトレベルチェック用の
securityPostDenormalize - 複雑な認可ロジック用のVoter
- Symfony Rate Limiter統合によるレート制限
#[ApiResource(
operations: [
new Get(
security: "is_granted('ROLE_USER')"
),
new Put(
security: "is_granted('ROLE_ADMIN') or object.getOwner() == user",
securityPostDenormalize: "is_granted('BOOK_EDIT', object)"
)
]
)]フィルターとページネーション: 高度なクエリパターン
API Platformフィルターにより、クライアントはURLパラメータでコレクションをクエリできます。4.2のフィルターシステムは、拡張性を向上させるために再設計されました。
use ApiPlatform\Doctrine\Orm\Filter\SearchFilter;
use ApiPlatform\Doctrine\Orm\Filter\DateFilter;
use ApiPlatform\Doctrine\Orm\Filter\OrderFilter;
use ApiPlatform\Metadata\ApiFilter;
#[ApiResource]
#[ApiFilter(SearchFilter::class, properties: [
'title' => 'partial', // LIKE %value%
'author.name' => 'exact' // Nested property
])]
#[ApiFilter(DateFilter::class, properties: ['createdAt'])]
#[ApiFilter(OrderFilter::class, properties: ['title', 'createdAt'])]
class Book { /* ... */ }生成されるエンドポイント:
GET /api/books?title=symfony # Search by title
GET /api/books?createdAt[after]=2026-01-01 # Date range
GET /api/books?order[createdAt]=desc # SortingAPI Platformリソースのテスト
API Platformは、機能テストを簡素化するテストクライアントを提供しています。ApiTestCaseクラスは、APIレスポンスに特化したアサーションを提供します。
namespace App\Tests\Api;
use ApiPlatform\Symfony\Bundle\Test\ApiTestCase;
use App\Entity\Book;
class BookTest extends ApiTestCase
{
public function testGetCollection(): void
{
$response = static::createClient()->request('GET', '/api/books');
$this->assertResponseIsSuccessful();
$this->assertResponseHeaderSame('content-type', 'application/ld+json; charset=utf-8');
$this->assertJsonContains([
'@context' => '/api/contexts/Book',
'@type' => 'Collection'
]);
}
public function testCreateBook(): void
{
$response = static::createClient()->request('POST', '/api/books', [
'json' => [
'title' => 'Symfony Best Practices',
'description' => 'A guide to modern Symfony development'
],
'headers' => ['Authorization' => 'Bearer ' . $this->getToken()]
]);
$this->assertResponseStatusCodeSame(201);
$this->assertJsonContains(['title' => 'Symfony Best Practices']);
}
public function testCreateBookValidationFails(): void
{
$response = static::createClient()->request('POST', '/api/books', [
'json' => ['description' => 'Missing title'],
'headers' => ['Authorization' => 'Bearer ' . $this->getToken()]
]);
$this->assertResponseStatusCodeSame(422);
$this->assertJsonContains([
'violations' => [
['propertyPath' => 'title', 'message' => 'This value should not be blank.']
]
]);
}
}API PlatformとSymfonyの重要ポイント
- State ProviderはGET操作を、State Processorはミューテーションを処理します。この分離により、カスタムデータソースとビジネスロジックを備えたクリーンなアーキテクチャが実現します
- Object MapperコンポーネントはAPIリソースをDoctrineエンティティから分離し、異なる読み取り/書き込みモデルを可能にし、内部構造を保護します
- JSON Streamerは、完全なメモリ割り当てなしでシリアライズすることで、コレクションエンドポイントで32%のパフォーマンス向上を実現します
- セキュリティは標準的なSymfonyメカニズムを通じて統合されます:
security式、Voter、Rate Limiterコンポーネント - バリデーショングループはオペレーションごとにコンストレイント適用をカスタマイズします
- フィルターは自動的にクエリパラメータを公開し、検索、日付、順序フィルターがほとんどのユースケースをカバーします
- 面接の質問はアーキテクチャ上の決定に焦点を当てます:カスタムProviderを使用するタイミング、読み取り/書き込みモデルの分離方法、セキュリティ実装パターン
今すぐ練習を始めましょう!
面接シミュレーターと技術テストで知識をテストしましょう。
Symfony のバグを見つけられますか
実際のコード、隠れたバグ、1日1回。アカウントなしで試せます。

執筆
Anthony Fillion-MailletSharpSkill 創業者
10 年以上フルスタック開発に携わっています。SharpSkill を運営し、ここで公開される内容に責任を負っています。
2026年9月8日 更新
タグ
共有
関連記事

API Platform Symfony REST:完全チュートリアルと面接対策 2026年版
API Platform 4.3を使用してSymfonyでREST APIを構築する方法を解説します。State Provider/Processorパターン、カスタムフィルター、セキュリティ設定、および技術面接で頻出する質問と回答を網羅した実践ガイドです。

Symfony面接質問集: 2026年トップ25
最も多く尋ねられるSymfony面接質問25選。アーキテクチャ、Doctrine ORM、サービス、セキュリティ、フォーム、テストを詳細な回答とコード例とともに解説。

Symfony Security 2026年版:Voters、ファイアウォール、技術面接で問われるポイント
Symfonyセキュリティコンポーネントの全体像を解説します。ファイアウォール設定、Voterによるきめ細かなアクセス制御、IsGranted属性、AccessTokenHandler、Decision Strategy、UserChecker、そして技術面接で頻出する質問と回答を網羅した実践ガイドです。