hoffmann / silex-view
Silex 的通用视图
This package is not auto-updated.
Last update: 2024-09-28 13:56:26 UTC
README
Silex-View 类似于 Django 类视图 和 Flask 可插入视图,是用于 PHP 微框架 Silex 的基于类的视图的实现。
在 Silex 中,您可以将闭包附加到路由上。以下是一个简单的示例。
$app->get('/blog/show/{id}', function (Application $app, Request $request, $id) { ... });
Silex 根据类型提示注入 $app
和 $request
变量。当路由匹配时,调用闭包,并将 $app
和 $request
绑定到您的 Silex 应用程序和当前请求。可以在函数定义中添加类似 $id
参数的路由变量。
这是一种构建小型应用的简单快捷方式。但在我看来,将控制器逻辑放在闭包中会导致代码紧密耦合,难以测试。
Silex 文档 展示了如何将控制器放在类中
$app->get('/', 'Igorw\Foo::bar'); use Silex\Application; use Symfony\Component\HttpFoundation\Request; namespace Igorw { class Foo { public function bar(Request $request, Application $app) { ... } } }
这种方法更好。现在您可以测试控制器类,使用模拟的 $request
和 $application
对象。作为奖励,您的路由定义小巧且干净,您的控制器与路由代码分离,可重用。
我不喜欢两点
-
您将控制器类作为字符串传递给路由函数。这可能是一种 PHP 方式,但这对我来说并不合适。而且,这让我烦恼的是,我选择的 IDE phpstrom 无法识别它,因此您不能点击它或使用转到定义快捷键。
-
您无法向控制器构造函数传递参数。这对我的影响更大。
Silex-View 有一个简单的 BaseView
类,您可以从中继承
use SilexView\BaseView class MyView extends BaseView { private $greeting; function __construct($greeting){ $this->greeting = $greeting; } function get($request, $app){ return $this->greeting.' '.$request->get('name'); } }
并在路由定义中使用它
$app->get('/hello/{name}', MyView::asView('hello'));
BaseView::asView()
是一个静态方法,它返回一个闭包,当路由匹配时将被调用
class BaseView { public static function asView() { $classname= get_called_class(); $args = func_get_args(); return function(\Symfony\Component\HttpFoundation\Request $request, \Silex\Application $app) use ($classname, $args){ $cls = new \ReflectionClass($classname); $instance = $cls->newInstanceArgs($args); return $instance->dispatch($request, $app); }; ...
传递给 asView
函数的所有参数都将转发到继承的控制器类的构造函数。受 Django 类视图 的启发,BaseView
类根据请求的 HTTP 方法分发请求。因此,GET
请求将传递到控制器的 get(..)
方法,而 POST
请求将传递到 post(...)
方法。使用这种约定,构建 REST 控制器非常简单且干净。
class BaseView { ... protected $http_method_names = array('get', 'post', 'put', 'delete', 'head', 'options', 'trace'); public function dispatch($request, $app) { $method = strtolower($request->getMethod()); //if no head method is defined use get if ("head" === $method && ! method_exists($this, "head")) $method = "get"; if (! (in_array($method, $this->http_method_names) && method_exists($this, $method))) return $this->httpMethodNotAllowed($method); return $this->$method($request, $app); }
TemplateView
类是用于渲染模板的 GET
请求的快捷方式。您只需要创建一个子类并实现 getContextData()
函数,该函数应返回一个数组,其中包含在您的 Twig 模板中需要的参数。
class MyTemplate extends TemplateView { function getContextData($request, $app) { return array('name' => "Joe"); } }
实现如下
class TemplateView extends BaseView { /* * Get the Template Name for the view * default implementation is to use the class name without namespace */ function getTemplateName(){ $cls = explode('\\', get_class($this)); return end($cls).'.twig'; } function get($request, $app) { return $app["twig"]->render($this->getTemplateName(), $this->getContextData($request, $app)); } function getContextData($request, $app) { } }