Slim Framework: routes and controllers

杀马特。学长 韩版系。学妹 提交于 2019-12-04 13:47:44

I guess I can share what I did with you guys. I noticed that every route method in Slim\Slim at some point called the method mapRoute:

Slim.php

 protected function mapRoute($args)
    {
        $pattern = array_shift($args);
        $callable = array_pop($args);
        $route = new \Slim\Route($pattern, $callable, $this->settings['routes.case_sensitive']);
        $this->router->map($route);
        if (count($args) > 0) {
            $route->setMiddleware($args);
        }

        return $route;
    }

In turn, the Slim\Route constructor called setCallable

Route.php

public function setCallable($callable)
    {
        $matches = [];
        if (is_string($callable) && preg_match('!^([^\:]+)\:([a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*)$!', $callable, $matches)) {
            $class = $matches[1];
            $method = $matches[2];
            //\Util\Helpers::prdie('Matches are', $matches);
            $callable = function () use ($class, $method) {
                static $obj = null;
                if ($obj === null) {
                    $obj = new $class;
                }
                return call_user_func_array([$obj, $method], func_get_args());
            };
        }

        if (!is_callable($callable)) {
            throw new \InvalidArgumentException('Route callable must be callable');
        }

        $this->callable = $callable;
    }

And this means that routes declared with a callable in the form Controller:method (note the single colon) were interpreted as non-static methods and therefore where instanced in the callable closure. So I extended Slim\Slim and Slim\Route. In the first one I overrode mapRoute

\Util\MySlim

 protected function mapRoute($args)
    {
        $pattern = array_shift($args);
        $callable = array_pop($args);
        $route = new \Util\MyRoute($this, $pattern, $callable, $this->settings['routes.case_sensitive']);
        $this->router->map($route);
        if (count($args) > 0) {
            $route->setMiddleware($args);
        }

        return $route;
    }

You see, when instancing \Util\MyRoute I pass the $app too, because in MyRoute there's such a protected property and the getCallable method uses it to instance the controller, thus allowing for non static methods to be used having the $app property already in them.

\Util\MyRoute.php

public function setCallable($callable)
{
    $matches = [];
    $app = $this->app;
    if (is_string($callable) && preg_match('!^([^\:]+)\:([a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*)$!', $callable, $matches)) {
        $class = $matches[1];
        $method = $matches[2];

        $callable = function () use ($app, $class, $method) {
            static $obj = null;
            if ($obj === null) {
                $obj = new $class($app);
            }
            return call_user_func_array([$obj, $method], func_get_args());
        };
    }

    if (!is_callable($callable)) {
        throw new \InvalidArgumentException('Route callable must be callable');
    }

    $this->callable = $callable;
}

So there it is. Using this two classes I can have $app injected into whatever Controller I declare on the route, as long as I use a single colon to separate controller from method. Using paamayim nekudotayim will call the method as static and therefore will throw an error if I try to access $this->app inside it.

I ran tests using blackfire.io and... the performance gain is negligible.

Pros:

  • this saves me the pain of calling $app = \Slim\Slim::getInstance() on every static method call accounting for about 100 lines of text overall.
  • it opens the way for further optimization by making every controller inherit from an abstract controller class, which in turn wraps the app methods into convenience methods.
  • it made me understand Slim's request and response lifecycle a little better.

Cons:

  • performance gains are negligible
  • you have to convert all your routes to use a single colon instead of paamayin, and all your controller methods from static to dynamic.
  • inheritance from Slim base classes might break when they roll out v 3.0.0
标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!