Structuring the router class in PHP with MVC

7

A friendly url of the type:

www.meusite.com.br/controlador/metodo/argumentos

It is handled in my Request class, where it "explodes" the url , separating it into segments, which are $controller , $action and $args respectively. returned to my Route class, where the "routing" of the application is done. Until then Ok.

Problem

The problem is simply adding a subdirectory. (So I complicate everything, since I'm a beginner in PHP applications with MVC, mainly in the concepts of classes Route and Request .)

Directory structure

What'scatchingisthat,asIdescribedtheprocessinthefirstparagraph,theapplicationwillworkperfectlywithoutthesub-directoriesUsrandAdm,havingonlythefollowinghierarchy.

Because the entire process is in accordance with Router and Request .

Class Router

class Router
{
    public static function run(Request $request)
    {
        $controller= $request->getController();
        $action= $request->getAction();
        $args = (array) $request->getArgs();
        $controller = 'Application\Controller\' . ucfirst($controller);
        $controller = new $controller();
        if (!is_callable(array($controller, $action))) {
            // Algum comando.
        }
        call_user_func_array(array($controller, $action), $args);
    }
    // Mais métodos

}

The above code is responsible for including Controllers and calling to methods based on what was returned by Request . (this does not have a lot of code, so I'll only put the snippet that treats url )

Request

public function __construct()
{
    if (!isset($_GET["url"])) return false;

    $segments = explode("/", $_GET["url"]);
    $this->controller = ($controller = array_shift($segments)) ? $controller : "index";
    $this->action = ($action = array_shift($segments)) ? $action : "main";
    $this->args = (is_array($segments[0])) ? $segments : array();
}

Question

I would like to know what changes I have to make in both codes, so that a call to a controller in any of the subdirectories can be successfully made using the following url

www.meusite.com.br/nome_do_subdiretorio/controlador/metodo/argumentos

I apologize for the size of the question, but I tried to make it complete.

Update

Controller Index

  

For example, with this controller, it would be the default if the url came as follows: www.meusite.com.br/nome_do_subdominio/

namespace Application\Adm\Controller;

use MamutePost\Controller;

class Index extends Controller
{
    // ... Métodos
}
  

MamutePost is a folder inside of Vendor where I put my "mini framework", which I developed to work with MVC.

    
asked by anonymous 21.02.2015 / 04:49

1 answer

5

Well initially I would change your class Request because as it is programmed it makes the mechanism of identifying routes very static for just this situation. Note how the simple class below makes it possible to identify generic routes in a regular expression.

class Router {

  private static $routes = array();

  private function __construct() {}
  private function __clone() {}

  public static function route($pattern, $callback) {
    $pattern = '/^' . str_replace('/', '\/', $pattern) . '$/';
    self::$routes[$pattern] = $callback;
  }

  public static function execute($url) {
    foreach (self::$routes as $pattern => $callback) {
      if (preg_match($pattern, $url, $params)) {
        array_shift($params);
        return call_user_func_array($callback, array_values($params));
      }
    }
  }
}

In this way, you record the routes of your application and use the callback function to call the appropriate driver:

//registro da rota http://www.meusite.com.br/index/main
Router::route('http://www.meusite.com.br/index/main', function(){
  print "Application\Index\Main" . "<br/>";
});

//registro da rota http://www.meusite.com.br/nome_do_subdiretorio/controlador/metodo/argumentos
Router::route('http://www.meusite.com.br/(\w+)/(\w+)/(\w+)/(\w+)', function($folder, $controller, $action, $args){
  print "Application\" . $folder . "\" . $controller . "<br/>";
});

so your requester would be in charge of just calling the route class by passing the url in question:

Router::execute("http://www.meusite.com.br/index/main");
Router::execute("http://www.meusite.com.br/nome_do_subdiretorio/controlador/metodo/argumentos");

a clean, simple and efficient approach to a basic route system credits: link

    
21.02.2015 / 06:54