2
\$\begingroup\$

I'm creating an app where the user will be able to create HTTP request matchers. So the RequestMatchers will match HTTP method, path, query parameters, etc., for incoming requests.

Can someone look over this gist to see if you think I'm on the right track for making it very extensible? Currently it only supports matching URLs, but that will grow and I want to make sure what I'm doing is reasonable moving forward.

RequestMatcher.php

namespace MyBundle/Entity;

// Persistable to "request_matchers" table
class RequestMatcher
{
    protected $urlMatcher;

    public function __construct(UrlMatcher $urlMatcher)
    {
        $this->urlMatcher = $urlMatcher;
    }

    public function getUrlMatcher()
    {
        return $this->urlMatcher;
    }
}

UrlMatcher.php

namespace MyBundle/Model;

abstract class UrlMatcher
{
    protected $path;

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

    public function getPath()
    {
        return $this->path;
    }
}

ExactUrlMatcher.php

namespace MyBundle/Entity;

// Persistable to "url_matchers" table, using a discriminator map column
class ExactUrlMatcher extends MyBundle\Model\UrlMatcher
{
}

ParameterizedUrlMatcher.php

namespace MyBundle/Entity;

// Persistable to "url_matchers" table, using a discriminator map column
class ParameterizedUrlMatcher extends MyBundle\Model\UrlMatcher
{
}

RequestMatchEvent.php

namespace MyBundle/Event;

class RequestMatchEvent extends Event
{
    protected $requestMatcher;

    protected $request;

    protected $matches = true;

    public function __construct(Reques $request, RequestMatcher $requestMatcher)
    {
        $this->request = $request;
        $this->->requestMatcher = $requestMatcher;
    }

    public function getRequestMatcher()
    {
        return $this->requestMatcher;
    }

    public function getRequest()
    {
        return $this->request;
    }

    public function setMatches($matches)
    {
        if ($this->matches) {
            $this->matches = (bool) $matches;
        }

        if (!$this->matches) {
            $this->stopPropagation();
        }

        return $this->matches;
    }

    public function isMatch()
    {
        return $this->matches;
    }
}

RequestMatchListener.php

namespace MyBundle/EventListener;

interface RequestMatchListener
{
    public function onMatchRequest(RequestMatchEvent $event);
}

ExactUrlRequestMatchListener.php

namespace MyBundle/EventListener;

// Registered with EventDispatcher
class ExactUrlRequestMatchListener implements RequestMatchListener
{
    public function onMatchRequest(RequestMatchEvent $event)
    {
        $urlMatcher = $event->getRequestMatcher()->getUrlMatcher();

        if (!$urlMatcher->getUrlMatcher() instanceof ExactUrlMatcher) {
            return true;
        }

        $request = $event->getRequest();

        $event->setMatches($urlMatcher->getPath() === $request->getUri());
    }
}

ParameterizedUrlRequestMatchListener.php

namespace MyBundle/EventListener;

// Registered with EventDispatcher
class ParameterizedUrlRequestMatchListener implements RequestMatchListener
{
    public function onMatchRequest(RequestMatchEvent $event)
    {  
        $urlMatcher = $$event->getRequestMatcher()->getUrlMatcher();

        if (!$urlMatcher->getUrlMatcher() instanceof ParameterizedUrlMatcher) {
            return true;
        }

        // determine if request matches
    }
}

Bringing it all together with RequestMatcherController.php

namespace MyBundle/Controller;

class RequestMatcherController extends BaseController
{
    protected $dispatcher;

    public function process(Request $request)
    {
        $requestMatchers = $this->getRequestMatcherRepository()->requestMatchersByUser($this->getCurrentUser());

        foreach ($requestMatchers as $requestMatcher) {

            $this->dispatcher->dispatch('matching.request', $event = new RequestMatchEvent($request, $requestMatcher));

            if ($event->isMatch()) {
                // Do something with $requestMatcher
            }
        }
    }
}
\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Browse other questions tagged or ask your own question.