最初,我的Slim Framework应用程序具有经典结构
(的index.php)
<?php
$app = new \Slim\Slim();
$app->get('/hello/:name', function ($name) {
echo "Hello, $name";
});
$app->run();
Run Code Online (Sandbox Code Playgroud)
但是当我添加更多路由和路由组时,我转向基于控制器的方法:
的index.php
<?php
$app = new \Slim\Slim();
$app->get('/hello/:name', 'HelloController::hello');
$app->run();
Run Code Online (Sandbox Code Playgroud)
HelloController.php
<?php
class HelloController {
public static function hello($name) {
echo "Hello, $name";
}
}
Run Code Online (Sandbox Code Playgroud)
这是有效的,它有助于组织我的应用程序结构,同时让我为每个控制器方法构建单元测试.
但是,我不确定这是正确的方法.我觉得我在mount特殊的基础上嘲笑Silex的方法,这不可能是好的.在每个Controller方法中使用$ app上下文需要我使用\ Slim\Slim :: getInstance(),这似乎不如使用$ app那样有效.
那么......是否存在一种既能提高效率又能实现订单效率的解决方案,还是以路径/封闭梦魇为代价来提高效率?
我想我可以和你们分享我的所作所为.我注意到Slim\Slim中的每个路由方法在某个时刻称为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;
}
Run Code Online (Sandbox Code Playgroud)
反过来,Slim\Route构造函数调用setCallable
Route.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 ($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;
}
Run Code Online (Sandbox Code Playgroud)
这意味着使用Controller:方法(注意单个冒号)以可调用方式声明的路由被解释为非静态方法,因此在可调用闭包中实例化.所以我扩展了Slim\Slim和Slim\Route.在第一个我覆盖 mapRoute
\的Util\MySlim
protected function mapRoute($args)
{
$pattern = array_shift($args);
$callable = array_pop($args);
$route = new \Util\MyRoute(
$this, // <-- now my routes have a reference to the App
$pattern,
$callable,
$this->settings['routes.case_sensitive']
);
$this->router->map($route);
if (count($args) > 0) {
$route->setMiddleware($args);
}
return $route;
}
Run Code Online (Sandbox Code Playgroud)
你看,当instancing\Util\MyRoute我也传递了$ app,因为在MyRoute中有这样一个受保护的属性,而getCallable方法使用它来实例化控制器,从而允许使用具有$ app属性的非静态方法在他们中.
\的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); // <--- now they have the App too!!
}
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;
}
Run Code Online (Sandbox Code Playgroud)
就是这样.使用这两个类,我可以将$ app注入我在路由上声明的任何控制器,只要我使用单个冒号将控制器与方法分开.使用paamayim nekudotayim将该方法称为静态,因此如果我尝试访问其中的$ this-> app,则会抛出错误.
我使用blackfire.io运行测试......性能提升可以忽略不计.
优点:
缺点:
| 归档时间: |
|
| 查看次数: |
10009 次 |
| 最近记录: |