PROGRAMMING

m9/ PHP
REMEMBERS




Last update:   23-07-2021

Dispatcher

Our framework is missing a major characteristic of any framework: extensibility. A developer must be able to hook into the framework life cycle. Like authentication or caching, for instance. EventDispatcher component is designed using Mediator Pattern. ! Your code dispatches an event to the dispatcher. Dispatcher notified all registered listeners for the event. Each listener does whatever it wants with the event. The framework must dispatch an event just before returning the Response instance.
 
// src/Simplex/Framework.php

namespace Simplex;

use Symfony\Component\EventDispatcher\EventDispatcher; // Look Here
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Routing\Exception\ResourceNotFoundException;
use Symfony\Component\Routing\Matcher\UrlMatcherInterface;
use Symfony\Component\HttpKernel\Controller\ControllerResolverInterface;
use Symfony\Component\HttpKernel\Controller\ArgumentResolverInterface;

class Framework
{
    private $dispatcher;
    private $matcher;
    private $controllerResolver;
    private $argumentResolver;

    public function __construct(
                EventDispatcher $dispatcher,
                    UrlMatcherInterface $matcher,
                        ControllerResolverInterface $controllerResolver,
                            ArgumentResolverInterface $argumentResolver)
    {
        $this->dispatcher = $dispatcher; // Look Here
        $this->matcher = $matcher;
        $this->controllerResolver = $controllerResolver;
        $this->argumentResolver = $argumentResolver;
    }

    public function handle(Request $request)
    {
        try {
            $request->attributes->add(
                $this->matcher->match($request->getPathInfo())
            );

            $controller =$this->controllerResolver->getController($request);
            $arguments =$this->argumentResolver
                ->getArguments($request, $controller);

            $response = call_user_func_array($controller, $arguments);
        } catch(ResourceNotFoundException $e) {
            $response = new Response('Not found', 404);
        } catch (\Exception $e) {
            $response = new Response('An error occured', 500);
        }

        $this->dispatcher->dispatch( // Look Here
            new ResponseEvent($response, $request), 'response'
        );

        return $response;
    }
}
... 41 lines
 
 
// src/Simplex/ResponseEvent.php

namespace Simplex;

use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Contracts\EventDispatcher\Event; // Look Here

class ResponseEvent extends Event
{
    private $request;
    private $response;

    public function __construct(Response $response, Request $request)
    {
        $this->response = $response;
        $this->request = $request;
    }

    public function getResponse()
    {
        return $this->response;
    }

    public function getRequest()
    {
        return $this->request;
    }
}
... 17 lines
 
 
// public/front.php

require_once __DIR__.'/../vendor/autoload.php';

use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Routing;
use Symfony\Component\HttpKernel\Controller\ControllerResolver;
use Symfony\Component\HttpKernel\Controller\ArgumentResolver;
use Symfony\Component\EventDispatcher\EventDispatcher;

$request = Request::createFromGlobals();
$routes = include __DIR__.'/../src/app.php';

$context = new Routing\RequestContext();
$context->fromRequest($request);
$matcher = new Routing\Matcher\UrlMatcher($routes, $context);

$dispatcher = new EventDispatcher(); // Look Here
$dispatcher->addListener('response', function(Simplex\ResponseEvent $event) {
    $response = $event->getResponse();
    $response->setContent(
        $response->getContent()." --- @Added with Dispatcher" // Look Here
    );
});

$controllerResolver = new ControllerResolver();
$argumentResolver = new ArgumentResolver();

$framework = new Simplex\Framework(
    $dispatcher, $matcher, $controllerResolver, $argumentResolver);
$response = $framework->handle($request);

$response->send();
... 20 lines
 
 
http://tests.local/php/framework/public/isEven/2
    // Yes, the number is even! --- @Added with Dispatcher
Framework v8.0 Let's move the Google listener to its own class.
 
// public/front.php
...

$dispatcher = new EventDispatcher();
$dispatcher->addListener(
    'response', [new Simplex\GoogleListener(), 'onResponse'], -255
);
$dispatcher->addListener(
    'response', [new Simplex\LoginListener(), 'onResponse']
);

$controllerResolver = new ControllerResolver();
$argumentResolver = new ArgumentResolver();

...
... 6 lines
 
 
// src/Simplex/GoogleListener.php

namespace Simplex;

Class GoogleListener
{
    public function onResponse(ResponseEvent $event) {

        $response = $event->getResponse();

        $response->setContent(
            $response->getContent() . "<-- GA CODE -->"
        );
    }
}
... 5 lines
 
 
./vendor/bin/phpunit --testdox

Framework (Simplex\Tests\Framework)
 รขล“ล“
Framework v8.2
Questions    
Symfony v5

        A B C D E F
๐Ÿ””
1/1