The Event System

Note: using Kernel event with API Platform should be mostly limited to tweaking the generated HTTP response. Also, GraphQL is not supported. For most use cases, better extension points, working both with REST and GraphQL, are available.

注: API プラットフォームでのカーネル イベントの使用は、ほとんどの場合、生成された HTTP 応答の微調整に限定されます。また、GraphQL はサポートされていません。ほとんどのユース ケースでは、REST と GraphQL の両方で動作する、より優れた拡張ポイントを利用できます。

API Platform Core implements the Action-Domain-Responder pattern. This implementation is covered in depth in the Creating custom operations and controllers chapter.

API Platform Core は、Action-Domain-Responder パターンを実装します。この実装については、カスタム操作とコントローラーの作成の章で詳しく説明しています。

Basically, API Platform Core executes an action class that will return an entity or a collection of entities. Then a series of event listeners are executed which validate the data, persist it in database, serialize it (typically in a JSON-LD document) and create an HTTP response that will be sent to the client.

基本的に、API Platform Core は、エンティティまたはエンティティのコレクションを返すアクション クラスを実行します。次に、一連のイベント リスナーが実行され、データが検証され、データベースに保存され、(通常は JSON-LD ドキュメントで) シリアル化され、クライアントに送信される HTTP 応答が作成されます。

To do so, API Platform Core leverages events triggered by the Symfony HTTP Kernel. You can also hook your own code to those events. There are handy and powerful extension points available at all points of the request lifecycle.

そのために、API Platform Core は Symfony HTTP カーネルによってトリガーされるイベントを利用します。独自のコードをこれらのイベントにフックすることもできます。リクエストのライフサイクルのすべてのポイントで、便利で強力な拡張ポイントを利用できます。

If you are using Doctrine, lifecycle events (ORM, MongoDB ODM) are also available if you want to hook into the persistence layer's object lifecycle.

Doctrine を使用している場合、永続化レイヤーのオブジェクト ライフサイクルにフックする場合は、ライフサイクル イベント (ORM、MongoDB ODM) も利用できます。

Built-in Event Listeners

These built-in event listeners are registered for routes managed by API Platform:

これらの組み込みイベント リスナーは、API プラットフォームによって管理されるルートに登録されます。

Name Event Pre & Post hooks Priority Description
AddFormatListener kernel.request None 7 Guesses the best response format (content negotiation)
QueryParameterValidateListener kernel.request None 16 Validates query parameters
ReadListener kernel.request PRE_READ, POST_READ 4 Retrieves data from the persistence system using the state providers (GET, PUT, PATCH, DELETE)
DeserializeListener kernel.request PRE_DESERIALIZE, POST_DESERIALIZE 2 Deserializes data into a PHP entity (POST); updates the entity retrieved using the state provider (PUT, PATCH)
DenyAccessListener kernel.request None 1 Enforces access control using Security expressions
ValidateListener kernel.view PRE_VALIDATE, POST_VALIDATE 64 Validates data (POST, PUT, PATCH)
WriteListener kernel.view PRE_WRITE, POST_WRITE 32 Persists changes in the persistence system using the state processors (POST, PUT, PATCH, DELETE)
SerializeListener kernel.view PRE_SERIALIZE, POST_SERIALIZE 16 Serializes the PHP entity in string according to the request format
RespondListener kernel.view PRE_RESPOND, POST_RESPOND 8 Transforms serialized to a Symfony\Component\HttpFoundation\Response instance
AddLinkHeaderListener kernel.response None 0 Adds a Link HTTP header pointing to the Hydra documentation
ValidationExceptionListener kernel.exception None 0 Serializes validation exceptions in the Hydra format
ExceptionListener kernel.exception None -96 Serializes PHP exceptions in the Hydra format (including the stack trace in debug mode)

Some of these built-in listeners can be enabled/disabled by setting operation attributes:

これらの組み込みリスナーの一部は、操作属性を設定することで有効/無効にできます。

Attribute Type Default Description
query_parameter_validate bool true Enables or disables QueryParameterValidateListener
read bool true Enables or disables ReadListener
deserialize bool true Enables or disables DeserializeListener
validate bool true Enables or disables ValidateListener
write bool true Enables or disables WriteListener
serialize bool true Enables or disables SerializeListener

Some of these built-in listeners can be enabled/disabled by setting request attributes (for instance in the defaults attribute of an operation):

これらの組み込みリスナーの一部は、リクエスト属性を設定することで有効/無効にできます (たとえば、操作の defaultsattribute で)。

Attribute Type Default Description
_api_receive bool true Enables or disables ReadListener, DeserializeListener, ValidateListener
_api_respond bool true Enables or disables SerializeListener, RespondListener
_api_persist bool true Enables or disables WriteListener

Custom Event Listeners

Registering your own event listeners to add extra logic is convenient.

独自のイベント リスナーを登録してロジックを追加すると便利です。

The ApiPlatform\Symfony\EventListener\EventPriorities class comes with a convenient set of class constants corresponding to commonly used priorities:

ApiPlatform\Symfony\EventListener\EventPriorities クラスには、一般的に使用される優先度に対応するクラス定数の便利なセットが付属しています。

Constant Event Priority
PRE_READ kernel.request 5
POST_READ kernel.request 3
PRE_DESERIALIZE kernel.request 3
POST_DESERIALIZE kernel.request 1
PRE_VALIDATE kernel.view 65
POST_VALIDATE kernel.view 63
PRE_WRITE kernel.view 33
POST_WRITE kernel.view 31
PRE_SERIALIZE kernel.view 17
POST_SERIALIZE kernel.view 15
PRE_RESPOND kernel.view 9
POST_RESPOND kernel.response 0

In the following example, we will send a mail each time a new book is created using the API:

次の例では、API を使用して新しい書籍が作成されるたびにメールを送信します。

<?php
// api/src/EventSubscriber/BookMailSubscriber.php

namespace App\EventSubscriber;

use ApiPlatform\Symfony\EventListener\EventPriorities;
use App\Entity\Book;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpKernel\Event\ViewEvent;
use Symfony\Component\HttpKernel\KernelEvents;
use Symfony\Component\Mime\Email;
use Symfony\Component\Mailer\MailerInterface;

final class BookMailSubscriber implements EventSubscriberInterface
{
    private $mailer;

    public function __construct(MailerInterface $mailer)
    {
        $this->mailer = $mailer;
    }

    public static function getSubscribedEvents()
    {
        return [
            KernelEvents::VIEW => ['sendMail', EventPriorities::POST_WRITE],
        ];
    }

    public function sendMail(ViewEvent $event): void
    {
        $book = $event->getControllerResult();
        $method = $event->getRequest()->getMethod();

        if (!$book instanceof Book || Request::METHOD_POST !== $method) {
            return;
        }

        $message = (new Email())
            ->from('system@example.com')
            ->to('contact@les-tilleuls.coop')
            ->subject('A new book has been added')
            ->text(sprintf('The book #%d has been added.', $book->getId()));

        $this->mailer->send($message);
    }
}

If you use the official API Platform distribution, creating the previous class is enough. The Symfony DependencyInjection component will automatically register this subscriber as a service and will inject its dependencies thanks to the autowiring feature.

公式の API Platform ディストリビューションを使用する場合は、以前のクラスを作成するだけで十分です。 Symfony の DependencyInjection コンポーネントは、このサブスクライバーをサービスとして自動的に登録し、オートワイヤー機能のおかげでその依存関係を注入します。

Alternatively, the subscriber must be registered manually.

または、加入者を手動で登録する必要があります。