thephpleague / route

Fast PSR-7 based routing and dispatch component including PSR-15 middleware, built on top of FastRoute.
http://route.thephpleague.com
MIT License
651 stars 126 forks source link

Dispatcher: handle and find #328

Open vanodevium opened 1 year ago

vanodevium commented 1 year ago

Is there any way to only find the specific handler, but not handle it?

In simple way, this is original dispatchRequest()

    public function dispatchRequest(ServerRequestInterface $request): ResponseInterface
    {
        $method = $request->getMethod();
        $uri    = $request->getUri()->getPath();
        $match  = $this->dispatch($method, $uri);

        switch ($match[0]) {
            case FastRoute::NOT_FOUND:
                $this->setNotFoundDecoratorMiddleware();
                break;
            case FastRoute::METHOD_NOT_ALLOWED:
                $allowed = (array) $match[1];
                $this->setMethodNotAllowedDecoratorMiddleware($allowed);
                break;
            case FastRoute::FOUND:
                $route = $this->ensureHandlerIsRoute($match[1], $method, $uri)->setVars($match[2]);

                if ($this->isExtraConditionMatch($route, $request)) {
                    $this->setFoundMiddleware($route);
                    $request = $this->requestWithRouteAttributes($request, $route);
                    break;
                }

                $this->setNotFoundDecoratorMiddleware();
                break;
        }

        return $this->handle($request);
    }

But I wanna method which return only $match array, without processing. Something like:

    public function dispatchAndReturn(ServerRequestInterface $request): array
    {
        $method = $request->getMethod();
        $uri    = $request->getUri()->getPath();
        return $this->dispatch($method, $uri);
    }
ericktucto commented 1 year ago

It's util to Clockwork. I created a DataSource to use on Clockwork

BEFORE

Captura desde 2023-05-14 20-58-06

AFTER

github

LeagueRouterDataSource

<?php

namespace App\DataSources;

use Clockwork\DataSource\DataSourceInterface;
use Clockwork\Request\Request;

use League\Route\Dispatcher;
use League\Route\Router;

// it is also necessary to obtain the array of routes
class AppRouter extends Router
{
  public function getData(): array
  {
    return $this->routeCollector->getData();
  }
}

class LeagueRouterDataSource implements DataSourceInterface
{
  public function __construct(
    protected AppRouter $router,
    protected ServerRequestInterface $request
  ) {
  }

  public function resolve(Request $request)
  {
    $request->controller = $this->getController();
  }

  protected function getController()
  {
    $data = $this->router->getData();
    $dispatcher = new Dispatcher($data);
    $dispatcher->setStrategy($this->router->getStrategy());

    $match = $dispatcher->dispatchAndReturn($this->request);
    // or
    // $match = $dispatcher->dispatch($method, $uri);
   // dispatch method is public and not be necessary create the dispatchAndReturn method
    $callable = $match[1]->getCallable();

    // if use magic method __invoke
    if (is_object($callable)) {
      return get_class($callable);
    }

    // if use syntax [controller, method] or "controller::method"
    if (is_array($callable)) {
      [$controller, $method] = $callable;
      return get_class($controller) . "@{$method}";
    }

    // if use anonymous function
    return "Closure";
  }
}