How to implement a Route System in MVC?

Asked

Viewed 1,377 times

5

I am creating an MVC Framework (more for studies), and I am trying to implement a route system, but I’m not sure how/where to run the routes. So I’d like to know if there’s any flow of execution of an MVC project.

Mine’s kind of like this:

// Função que inicia a aplicação
RUN() {

   // Aqui faço as chamadas padrões, detecto qual é o Controller e Action
   // da requisição
   Request $request = new Request();

   // Pego o Controller;
   string $controller = $request->getController();

   // Pego a Action
   string $action = $request->getAction();

   // Instâncio o Controller
   Controller $app = New $controller($request);

   string $output = $app->{$action}();

   // Imprimo o resultado (view)
   output($output);

}

Source Code

Controller and action execution would continue in the above scope, or within the route scope?

I saw that some route systems (almost all actually), use a "Handler" (_callback) for the route. In this case where the action?

Note: I’m doing the framework in PHP, but I’m looking for a more "theoretical" answer, like a language-independent algorithm, it could be in the same style as the code I put up, without too much detail, just the same logic.

Note²: The answer does not need to be a TCC. :P

  • This question may help you > http://answall.com/questions/60830/quando-o-controller%C3%A9-necess%C3%A1rio

  • Thanks Lucaoa, it sure will help a lot. : D

  • The routes are usually run by a "Dispatcher", who is the guy responsible for Dispachar’s request. Take a look at the framework I played Phplegends/Maxters. It uses components that are installed via Composer, among them the Phplegends/Routes

  • It’s not jabá! take a look at example

1 answer

3


I usually do it this way:

Collection - The collection that will store all routes.

Route - The class that represents a route. You must provide information like the Uri you want to capture and http verbs accepted.

Router - The class that serves to bridge the gap between Route and Collection. It is a facilitator to create routes within the collection.

Dispatcherinterface - The interface that provides a method to be executed as the route dispatcher. I preferred to make an interface to be able to meet several implementations, for example, someone who wants to use a more complex library or who simply wanted to use less resources.

So in that context, we would have a structure something like this:

$router = new Router(new Collection);

// Cria a instância de Route, coloca dentro da Collection
// E retorna Rota recém-criada, para possíveis outra definições 

$router->get('/', 'HomeController::getIndex'); 

$router->get('/login', function () {})->setName('home.login');

// Classe que implementa DispatcherInterface
$router->dispatch(new Dispatcher());

Based on the context presented in the question, I think an interesting one would be:

$request = new Request();

// retorna new Response se tudo der certo

$response = $router->dispatch(new RequestDispatcher($request)); 


$response->send();

Within your RequestDispatcher, you could apply the proper operations to call Controller and Method.

For example:

   class RequestDispatcher implements DispatcherInterface {

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

       public function dispatch(Router $router) {
            $route = $router->findByRequest($this->request);

            if (! $route) return $this->notFound();

            $response = call_user_func($route->callAction(), $route->getParameters());

            return $response;


       }
   }

That is, in your Dispatcher, you can add the operations needed to search for the route within the collection. When not found, you can invoke an action to lasso the 404 error. When it is found, you can call the action set to the given url and call it, then return a Response.

Trying to sum it up:

Dispatcher searches the route within a collection of routes, which was created by the router. Then, if Dispatcher finds the route, it converts the return of the route action (Can be a Controller method or a Closure) to a Response, which is finally sent to the output.

You quoted in your question regarding a Handler, which is passed through a callback.

I believe you are talking about an anonymous function, which some libraries use to "tie" a certain functionality to a route in order to run at the end.

In my library I also did this. I can use both a class method (the Controller) and an anonymous function. I think this is very useful in cases where the route does not make sense to point to a specific controller, because it is not something that does not have "relationship" with the rest.

Example:

   $router->get('/json/cep/{num}', function ($number) {

        $url = sprintf('https://cep.correios.com.br/%s.json', $number);

        $dados = json_decode(file_get_contents($url));

        // Transforma em JsonResponse
        return $dados;
   });
  • Cool Wallace, I could quite understand the idea. Just left to talk about Handler, that even you set an "example: $router->get('/login', function () {})->setName('home.login');, which would be that anonymous function. Explain to me also this name home.login, I’ve seen it in other places, it would be controller.action? Thanks!

  • @Kaduamaral would be an internal name for the route. Instead of you do redirect('/login') you would do redirect_route('home.login'). It’s just a way to organize better by naming the routes

Browser other questions tagged

You are not signed in. Login or sign up in order to post.