[START CHUNK 2/4]
### test.txt ###

listeners.

Listeners or Subscribers
Listeners and subscribers can be used in the same application indistinctly. The decision to use either of them is usually a matter of personal taste. However, there are some minor advantages for each of them:

Subscribers are easier to reuse because the knowledge of the events is kept in the class rather than in the service definition. This is the reason why Symfony uses subscribers internally;
Listeners are more flexible because bundles can enable or disable each of them conditionally depending on some configuration value.
Event Aliases
When configuring event listeners and subscribers via dependency injection, Symfony's core events can also be referred to by the fully qualified class name (FQCN) of the corresponding event class:

 Copy
// src/EventSubscriber/RequestSubscriber.php
namespace App\EventSubscriber;

use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Symfony\Component\HttpKernel\Event\RequestEvent;

class RequestSubscriber implements EventSubscriberInterface
{
 public static function getSubscribedEvents(): array
 {
 return [
 RequestEvent::class => 'onKernelRequest',
 ];
 }

 public function onKernelRequest(RequestEvent $event)
 {
 // ...
 }
}
Internally, the event FQCN are treated as aliases for the original event names. Since the mapping already happens when compiling the service container, event listeners and subscribers using FQCN instead of event names will appear under the original event name when inspecting the event dispatcher.

This alias mapping can be extended for custom events by registering the compiler pass AddEventAliasesPass:

 Copy
// src/Kernel.php
namespace App;

use App\Event\MyCustomEvent;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\EventDispatcher\DependencyInjection\AddEventAliasesPass;
use Symfony\Component\HttpKernel\Kernel as BaseKernel;

class Kernel extends BaseKernel
{
 protected function build(ContainerBuilder $containerBuilder)
 {
 $containerBuilder->addCompilerPass(new AddEventAliasesPass([
 MyCustomEvent::class => 'my\_custom\_event',
 ]));
 }
}
The compiler pass will always extend the existing list of aliases. Because of that, it is safe to register multiple instances of the pass with different configurations.

Debugging Event Listeners
You can find out what listeners are registered in the event dispatcher using the console. To show all events and their listeners, run:

php bin/console debug:event-dispatcher
You can get registered listeners for a particular event by specifying its name:

php bin/console debug:event-dispatcher kernel.exception
or can get everything which partial matches the event name:

php bin/console debug:event-dispatcher kernel // matches "kernel.exception", "kernel.response" etc.
php bin/console debug:event-dispatcher Security // matches "Symfony\Component\Security\Http\Event\CheckPassportEvent"
The security system uses an event dispatcher per firewall. Use the --dispatcher option to get the registered listeners for a particular event dispatcher:

php bin/console debug:event-dispatcher --dispatcher=security.event\_dispatcher.main
How to Set Up Before and After Filters
It is quite common in web application development to need some logic to be performed right before or directly after your controller actions acting as filters or hooks.

Some web frameworks define methods like preExecute() and postExecute(), but there is no such thing in Symfony. The good news is that there is a much better way to interfere with the Request -> Response process using the EventDispatcher component.

Token Validation Example
Imagine that you need to develop an API where some controllers are public but some others are restricted to one or some clients. For these private features, you might provide a token to your clients to identify themselves.

So, before executing your controller action, you need to check if the action is restricted or not. If it is restricted, you need to validate the provided token.

Please note that for simplicity in this recipe, tokens will be defined in config and neither database setup nor authentication via the Security component will be used.

Before Filters with the kernel.controller Event
First, define some token configuration as parameters:

 Copy
# config/services.yaml
parameters:
 tokens:
 client1: pass1
 client2: pass2
Tag Controllers to Be Checked
A kernel.controller (aka KernelEvents::CONTROLLER) listener gets notified on every request, right before the controller is executed. So, first, you need some way to identify if the controller that matches the request needs token validation.

A clean and easy way is to create an empty interface and make the controllers implement it:

 Copy
namespace App\Controller;

interface TokenAuthenticatedController
{
 // ...
}
A controller that implements this interface looks like this:

 Copy
namespace App\Controller;

use App\Controller\TokenAuthenticatedController;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;

class FooController extends AbstractController implements TokenAuthenticatedController
{
 // An action that needs authentication
 public function bar()
 {
 // ...
 }
}
Creating an Event Subscriber
Next, you'll need to create an event subscriber, which will hold the logic that you want to be executed before your controllers. If you're not familiar with event subscribers, you can learn more about them at Events and Event Listeners:

 Copy
// src/EventSubscriber/TokenSubscriber.php
namespace App\EventSubscriber;

use App\Controller\TokenAuthenticatedController;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Symfony\Component\HttpKernel\Event\ControllerEvent;
use Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException;
use Symfony\Component\HttpKernel\KernelEvents;

class TokenSubscriber implements EventSubscriberInterface
{
 public function \_\_construct(
 private $tokens
 ) {
 }

 public function onKernelController(ControllerEvent $event)
 {
 $controller = $event->getController();

 // when a controller class defines multiple action methods, the controller
 // is returned as [$controllerInstance, 'methodName']
 if (is\_array($controller)) {
 $controller = $controller[0];
 }

 if ($controller instanceof TokenAuthenticatedController) {
 $token = $event->getRequest()->query->get('token');
 if (!in\_array($token, $this->tokens)) {
 throw new AccessDeniedHttpException('This action needs a valid token!');
 }
 }
 }

 public static function getSubscribedEvents()
 {
 return [
 KernelEvents::CONTROLLER => 'onKernelController',
 ];
 }
}
That's it! Your services.yaml file should already be setup to load services from the EventSubscriber directory. Symfony takes care of the rest. Your TokenSubscriber onKernelController() method will be executed on each request. If the controller that is about to be executed implements TokenAuthenticatedController, token authentication is applied. This lets you have a "before" filter on any controller you want.

If your subscriber is not called on each request, double-check that you're loading services from the EventSubscriber directory and have autoconfigure enabled. You can also manually add the kernel.event\_subscriber tag.

After Filters with the kernel.response Event
In addition to having a "hook" that's executed before your controller, you can also add a hook that's executed after your controller. For this example, imagine that you want to add a sha1 hash (with a salt using that token) to all responses that have passed this token authentication.

Another core Symfony event - called kernel.response (aka KernelEvents::RESPONSE) - is notified on every request, but after the controller returns a Response object. To create an "after" listener, create a listener class and register it as a service on this event.

For example, take the TokenSubscriber from the previous example and first record the authentication token inside the request attributes. This will serve as a basic flag that this request underwent token authentication:

 Copy
public function onKernelController(ControllerEvent $event)
{
 // ...

 if ($controller instanceof TokenAuthenticatedController) {
 $token = $event->getRequest()->query->get('token');
 if (!in\_array($token, $this->tokens)) {
 throw new AccessDeniedHttpException('This action needs a valid token!');
 }

 // mark the request as having passed token authentication
 $event->getRequest()->attributes->set('auth\_token',
[END CHUNK 2/4]
Reply with OK: [CHUNK x/TOTAL], don't reply anything else, don't explain the text!
[시작 청크 2/4]test.txt ### ###리스너.리스너 또는 구독자리스너와 구독자는 동일한 애플리케이션에서 구분 없이 사용할 수 있습니다. 둘 중 하나를 사용하는 것은 일반적으로 개인적인 취향의 문제입니다. 그러나 각각에 대해 몇 가지 사소한 이점이 있습니다:구독자는 이벤트에 대한 지식이 서비스 정의가 아닌 클래스에 유지되므로 재사용하기가 더 쉽습니다. 이것이 바로 심포니가 내부적으로 구독자를 사용하는 이유입니다;수신자는 번들이 일부 구성 값에 따라 조건부로 각각을 활성화 또는 비활성화할 수 있기 때문에 더 유연합니다.이벤트 별칭종속성 주입을 통해 이벤트 리스너와 구독자를 구성할 때 Symfony의 핵심 이벤트는 해당 이벤트 클래스의 정규화된 클래스 이름(FQCN)으로도 참조할 수 있습니다: 복사// src/EventSubscriber/RequestSubscriber.php네임스페이스 App\EventSubscriber;사용 심포니\컴포넌트\이벤트디스패처\이벤트서브스크립터인터페이스;사용 심포니\컴포넌트\Http커널\이벤트\리퀘스트이벤트;RequestSubscriber 클래스 구현 이벤트 구독자 인터페이스{ 공용 정적 함수 getSubscribedEvents(): array { return [ RequestEvent::class => 'onKernelRequest', ]; } public function onKernelRequest(RequestEvent $event) { // ... }}내부적으로 이벤트 FQCN은 원래 이벤트 이름의 별칭으로 취급됩니다. 서비스 컨테이너를 컴파일할 때 이미 매핑이 이루어지기 때문에 이벤트 리스너와 구독자가 이벤트 이름 대신 FQCN을 사용하면 이벤트 디스패처를 검사할 때 원래 이벤트 이름 아래에 나타납니다.이 별칭 매핑은 컴파일러 패스 AddEventAliasesPass를 등록하여 사용자 지정 이벤트에 대해 확장할 수 있습니다: Copy// src/Kernel.php네임스페이스 App;사용 App\Event\MyCustomEvent;사용 심포니\컴포넌트\디펜던시인젝션\컨테이너빌더;사용 심포니\ 컴포넌트\ 이벤트 디스패처\ 의존성 주입\ 추가 이벤트 별칭 패스;심포니\컴포넌트\Http커널\커널을 베이스커널로 사용합니다;Kernel 클래스는 BaseKernel을 확장합니다.{ protected 함수 빌드(컨테이너 빌더 $containerBuilder) { $containerBuilder->addCompilerPass(new AddEventAliasesPass([[ MyCustomEvent::class => 'my\_custom\_event', ])); }}컴파일러 패스는 항상 기존 별칭 목록을 확장합니다. 따라서 서로 다른 구성으로 패스의 여러 인스턴스를 등록하는 것이 안전합니다.이벤트 리스너 디버깅콘솔을 사용하여 이벤트 디스패처에 어떤 리스너가 등록되어 있는지 확인할 수 있습니다. 모든 이벤트와 해당 리스너를 표시하려면 다음을 실행하세요:php bin/console debug:event-dispatcher특정 이벤트의 이름을 지정하여 등록된 리스너를 가져올 수 있습니다:php bin/console debug:event-dispatcher kernel.exception또는 이벤트 이름과 부분적으로 일치하는 모든 것을 가져올 수 있습니다:php bin/console debug:event-dispatcher 커널 // "kernel.exception", "kernel.response" 등과 일치합니다.php bin/console debug:event-dispatcher Security // "Symfony\Component\Security\Http\Event\CheckPassportEvent"와 일치합니다.보안 시스템은 방화벽당 이벤트 디스패처를 사용합니다. 특정 이벤트 디스패처에 등록된 리스너를 가져오려면 --dispatcher 옵션을 사용합니다:php bin/console debug:event-dispatcher --dispatcher=security.event\_dispatcher.main전후 필터 설정 방법웹 애플리케이션 개발에서 필터 또는 후크 역할을 하는 컨트롤러 액션 직전 또는 직후에 일부 로직을 수행해야 하는 경우가 매우 흔합니다.일부 웹 프레임워크에서는 사전 실행() 및 사후 실행()과 같은 메서드를 정의하지만 Symfony에는 이러한 메서드가 없습니다. 좋은 소식은 이벤트 디스패처 컴포넌트를 사용하여 요청 -> 응답 프로세스에 간섭하는 훨씬 더 좋은 방법이 있다는 것입니다.토큰 유효성 검사 예제일부 컨트롤러는 공개되지만 다른 컨트롤러는 하나 또는 일부 클라이언트로 제한되는 API를 개발해야 한다고 가정해 보겠습니다. 이러한 비공개 기능의 경우, 클라이언트에 토큰을 제공하여 자신을 식별할 수 있습니다.따라서 컨트롤러 액션을 실행하기 전에 해당 액션이 제한되는지 여부를 확인해야 합니다. 제한된 경우 제공된 토큰의 유효성을 검사해야 합니다.이 레시피에서는 간단하게 하기 위해 토큰을 구성에서 정의하고 데이터베이스 설정이나 보안 컴포넌트를 통한 인증은 사용하지 않습니다.kernel.controller 이벤트로 필터링 전 단계먼저 몇 가지 토큰 구성을 파라미터로 정의합니다: 복사# config/services.yaml매개변수를 복사합니다: tokens: client1: pass1 client2: pass2검사할 태그 컨트롤러컨트롤러가 실행되기 직전에 모든 요청에 대해 kernel.controller(일명 KernelEvents::CONTROLLER) 리스너가 알림을 받습니다. 따라서 먼저 요청과 일치하는 컨트롤러에 토큰 유효성 검사가 필요한지 식별할 수 있는 방법이 필요합니다.깔끔하고 쉬운 방법은 빈 인터페이스를 생성하고 컨트롤러가 이를 구현하도록 하는 것입니다: 복사네임스페이스 App\Controller;인터페이스 TokenAuthenticatedController{ // ...}이 인터페이스를 구현하는 컨트롤러는 다음과 같습니다: Copy네임스페이스 App\Controller;사용 App\Controller\TokenAuthenticatedController;사용 Sym