# Automatic Routing (attempt 2)

**URL:** <https://discourse.slimframework.com/t/automatic-routing-attempt-2/1571>\
**Category:** Questions\
**Created:** [June 15, 2017, 10:54am UTC](https://discourse.slimframework.com/t/automatic-routing-attempt-2/1571 "2017-06-15T10:54:08Z")\
**Posts on this page:** 3\
**Page:** 1

<div class="post-metadata">

**Author:** ![marcelloh](https://yyz2.discourse-cdn.com/flex030/user_avatar/discourse.slimframework.com/marcelloh/32/404_2.png) [@marcelloh](https://discourse.slimframework.com/u/marcelloh)\
**Post date:** [June 15, 2017, 10:54am UTC](https://discourse.slimframework.com/t/automatic-routing-attempt-2/1571/1 "2017-06-15T10:54:08Z")

</div>

Just to check if I have something worth using & sharing 🙂  
All routing goes to the corresponding controllers which reside in Modules.  
Modules  
– Front  
---- MainController  
---- AnotherFrontController  
– Admin  
---- AdminController  
---- UserController

So if you call /admin/user/list

if will auto-magically go to the edit function within the UserController

routes.php:

```
<?php
/**
 * All the routes to their corresponding controllers
 *
 * The first param is the start of the url
 * Example:
 * every url starting with /admin will be handled by the configured controller
 *
 */
use MyApp\Common\Helpers\RouteResolver;

$app->any('[/{args:.*}]', function ($request, $response, $args) use($app)
{
    $obRouteResolver = new RouteResolver($this, $request, $response, $args);
	return $obRouteResolver->call($this, $request, $response, $args);
});

```

RouteResolver.php:

```
<?php

namespace MyApp\Common\Helpers;

/**
 * Class routeResolver
 * creates dynamic routing functionality
 * routes url to the correct controller->action($args)
 */
class RouteResolver
{
    /**
     * Call a given class / method
     *
     * @param string $container
     * @param string $request
     * @param string $response
     * @param array $args
     *
     * @return \Psr\Http\Message\ResponseInterface
     * @throws \Exception
     */
    public function call($container, $request, $response, $args)
    {
        $args = explode('/', $args['args']);

        $reflection = $this->getControllerClass($args);

        $method = $this->getMethod($reflection, $args);
        if (!$method)
        {
            throw new \Exception('Method ' . $method->getName() . ' not found in ' . $reflection->getName());
        }

        $params['args'] = $args;

        $oClass = $reflection->newInstanceArgs([$container, $request, $response]);

        $ret = $method->invokeArgs($oClass, $params);

        if ($ret instanceof ResponseInterface) {
            $response = $ret;
        } elseif (is_string($ret) || is_numeric($ret)) {
            $response->write($ret);
        }

        return $response;
    }

    /**
     * Get the correct controller class
     *
     * @param $nameSpace
     * @param $route
     * @param $defaultRoute
     * @param $args
     *
     * @return \ReflectionClass
     */
    private function getControllerClass(&$args)
    {
        $reflection = false;

        // test if argument 1 is a controller
        if (@$args[1])
        {
            $reflection = $this->getReflection($args, 1);
        }

        // test if argument 0 is a controller
        if (@$args[0] && !$reflection) {
            $reflection = $this->getReflection($args, 0);
        }

        // get default controller
        if (!$reflection) {
            $reflection = $this->getReflection($args);
        }

        return $reflection;
    }

    /**
     * Try to load the reflection class of the controller
     *
     * @param $args
     * @param int $argNr
     *
     * @return bool|\ReflectionClass
     */
    private function getReflection(&$args, $argNr = -1)
    {
        if ($argNr == 1) {
            $domain = ucfirst($args[0]);
            $controller = ucfirst($args[1]);
        } elseif ($argNr == 0) {
            $domain = ucfirst($args[0]);
            $controller = ucfirst($args[0]);
        }
        else {
            $domain = 'Frontend';
            $controller = 'Frontend';
        }

        $nameSpace = 'MyApp\Modules\\';
        $route = $domain . '\Controllers\\' . $controller . 'Controller';

        $fullControllerName = $nameSpace . $route;
        //var_dump($fullControllerName);

        try {
            $reflection = new \ReflectionClass($fullControllerName);

            for ($i = 0; $i <= $argNr; $i++){
                unset($args[$i]);
            }
            $args = array_values($args);
        } catch (\ReflectionException $e) {
            $reflection = false;
        }

        return $reflection;
    }

    /**
     * Try to load the method of the reflection class of the controller
     *
     * @param $reflection
     * @param $args
     *
     * @return bool|\ReflectionMethod
     */
    private function getMethod($reflection, &$args)
    {
        $func = false;
        if ($args) {
            $func = $args[0];
            unset($args[0]);
            $args = array_values($args);
        }

        if (!$func) {
            $func = 'index'; // default action in a controller
        }

        try {
            $method = $reflection->getMethod($func);
        } catch (\ReflectionException $e) {
            $method = false;
        }

        return $method;
    }
}
```

---

<div class="post-metadata">

**Author:** ![silentworks](https://yyz2.discourse-cdn.com/flex030/user_avatar/discourse.slimframework.com/silentworks/32/10_2.png) [@silentworks](https://discourse.slimframework.com/u/silentworks)\
**Post date:** [June 15, 2017, 11:43am UTC](https://discourse.slimframework.com/t/automatic-routing-attempt-2/1571/2 "2017-06-15T11:43:16Z")

</div>

This might just be overcomplicating the system. This is how Codeigniter does it and this is one of the reason people moved away from it.

---

<div class="post-metadata">

**Author:** ![marcelloh](https://yyz2.discourse-cdn.com/flex030/user_avatar/discourse.slimframework.com/marcelloh/32/404_2.png) [@marcelloh](https://discourse.slimframework.com/u/marcelloh)\
**Post date:** [July 27, 2017, 8:58am UTC](https://discourse.slimframework.com/t/automatic-routing-attempt-2/1571/3 "2017-07-27T08:58:41Z")

</div>

For people who want to experiment with it, here a little more of what is does:

/something

- this is not an existing module (the Modules/Something/Controllers/SomethingController does not exist)  
so it decides it’s a function of the default controller  
So in the Modules/Frontend/Controllers/FrontendController there should be a function called “somewhere”

/admin

- this is an existing module (the Modules/Admin/Controllers/AdminController does exist)  
but no further argument was found, so the standard argument is "index"  
So in the Modules/Admin/Controllers/AdminController there should be a function called “index”

/admin/something

- this is not an existing module (the Modules/Admin/Controllers/SomethingController does not exist)  
so it decides it’s a function of the AdminController (because that one does exist)  
So in the Modules/Admin/Controllers/AdminController there should be a function called “somewhere”

/admin/user

- this is an existing module (the Modules/Admin/Controllers/UserController does exist)  
so it decides it’s a function of the UserController (because that one does exist)  
but no further argument was found, so the standard argument is "index"  
So in the Modules/Admin/Controllers/UserController there should be a function called “index”

/admin/user/list

- this is an existing module (the Modules/Admin/Controllers/UserController does exist)  
so it decides it’s a function of the UserController (because that one does exist)  
the argument is "list"  
So in the Modules/Admin/Controllers/UserController there should be a function called “list”

/admin/user/edit/12

- this is an existing module (the Modules/Admin/Controllers/UserController does exist)  
so it decides it’s a function of the UserController (because that one does exist)  
the argument is “edit” and 12  
So in the Modules/Admin/Controllers/UserController there should be a function called “edit” which receives the argument “12”
