steampixel / simplePHPRouter

This is a simple and small single class PHP router that can handel the whole url routing for your project.
MIT License
406 stars 117 forks source link

add Route by #52

Closed btinet closed 2 years ago

btinet commented 2 years ago

Hi Steampixel,

thanks a lot for your great work!

I tried to list all my routes into a .yaml-file and then call the correspondending Controller. It works as it should, but as you can see below, I have to differentiate between routes with and without variables in the expression, because the function appears not to work if there is no id oder slug or so. Like you can see, the only difference in the condition is the route value. Do you have any suggestions to simplify that? Is it also possible to use an array instead of comma-seperated values for the expression vars?

Thank you in advance and kind regards, Ben

//[...]

public function addRoutes()
    {
        foreach ($this->routes as $route)
        {
            if($route['value'])
            {
                $this->routing->add($route['expression'], function ($id) use ($route) {
                    try {
                        return $this->runControllerMethod($route['controller'], $route['method'], $id);
                    } catch (Exception $e) {
                        return 'Exception abgefangen: '. $e->getMessage() . "\n";
                    }
                }, $route['request']);
            } else {
                $this->routing->add($route['expression'], function () use ($route) {
                    try {
                        return $this->runControllerMethod($route['controller'], $route['method']);
                    } catch (Exception $e) {
                        return 'Exception abgefangen: '. $e->getMessage() . "\n";
                    }
                }, $route['request']);
            }
        }
    }

//[...]
steampixel commented 2 years ago

Hey Ben,

have you ever considered to use the func_get_args() function which is build in natively in PHP? Check this out: https://www.php.net/manual/en/function.func-get-args.php Just call this function within your anonymous function. It will return an array of all given function arguments. With this method you don't have to define your args within the anonymous function header. Just leave it empty like this (untested):

public function addRoutes()
    {
        foreach ($this->routes as $route)
        {
                $this->routing->add($route['expression'], function () use ($route) {
                    $arguments = func_get_args();
                    try {
                        return $this->runControllerMethod($route['controller'], $route['method'], $arguments);
                    } catch (Exception $e) {
                        return 'Exception abgefangen: '. $e->getMessage() . "\n";
                    }
                }, $route['request']);

        }
    }

This would be maybe a good example for the readme.md

steampixel commented 2 years ago

Also this may help: https://www.php.net/manual/en/functions.arguments.php#functions.variable-arg-list

btinet commented 2 years ago

Thanks a lot for your fast response. I will give it a try. Very good idea. I did not think of that yet.

btinet commented 2 years ago

It works as expected. Thank you very much, my dear!

Have a nice weekend. kind regards, Ben

btinet commented 2 years ago

There is one little thing I like to add, because it fits very good to your suggestion:

I call the controller's method with call_user_func_array(). So I don't need to get the vars out of the array given by func_get_args().

I call the controller method like this:

private function runControllerMethod($class, $method, array $mandatory = array())
    {
        if (!class_exists($class)) {
            throw new Exception('Class not found.');
        }
        $class = new $class;
        if(!method_exists($class,$method)) {
            throw new Exception('Method not found.');
        }
        return call_user_func_array(array($class, $method), $mandatory);
    }

Then I can use all given vars like that:

class AppController
{
    public function index($a, $b, $c, $d): string
    {
        return "$a, $b, $c and $d";
    }
}

kind regards, Ben