talesoft / tale-controller
适用于 talesoft/tale-app 的控制器中间件
Requires
- php: >=5.5.0
- psr/http-message: ~1.0
- talesoft/tale-app: ~0.1
- talesoft/tale-http-runtime: ~0.1
- talesoft/tale-inflector: ~0.1
- talesoft/tale-loader: ~0.1
This package is auto-updated.
Last update: 2024-09-10 08:11:54 UTC
README
一个 Tale 框架组件
什么是 Tale 控制器?
talesoft/tale-app
的中间件,允许轻松实例化和处理控制器。
您可以使用单个静态控制器,或者使用自动处理所有内容的调度器。
安装
通过 Composer 安装
composer require "talesoft/tale-controller:*"
composer install
用法
单次使用
单个控制器可以组成整个网站。这对于有 5-10 个子页的小网站非常有用。无需配置。
use Tale\App; use Tale\Controller; //Define a controller of some kind class MyController extends Controller { //GET|POST / public function indexAction() { $res = $this->getResponse(); $res->getBody()->write('Hello index!'); return $res; } //GET|POST /?action=about-us public function aboutUsAction() { $res = $this->getResponse(); $res->getBody()->write('About us!'); return $res; } //GET /?action=contact public function getContactAction() { $res = $this->getResponse(); $res->getBody()->write('Contact form!'); return $res; } //POST /?action=contact public function postContactAction() { //Handle contact form $res = $this->getResponse(); $res->getBody()->write('Success!'); return $res; } } //Create a new app context $app = new App(); //Make sure we can target the "action" somehow. //Normally you'd use a router, we use a simple GET-variable in this case //"index.php?action=about-us" would dispatch "MyController->aboutUsAction" //This is a simple middleware mapping query's "action" to the required request attribute "action" $app->append(function($req, $res, $next) { $params = $req->getQueryParams(); $action = isset($params['action']) ? $params['action'] : null; if ($action) $req = $req->withAttribute('action', $action); return $next($req, $res); }); //Append our controller middleware $app->append(MyController::class); //Display the app $app->display();
使用调度器
当应用变大时,您希望将功能拆分为单个模块。使用调度器,您可以控制自动控制器调度机制。
想象以下控制器结构
/
/index.php
/app
/controllers
IndexController.php
ContactController.php
PortfolioController.php
/Admin
/IndexController.php
这是调度器可以处理的常见情况,配置简单。
use Tale\App; use Tale\Controller\Dispatcher; //Create a new app context $app = new App([ 'controller' => [ 'nameSpace' => 'My\\Controllers', 'loader' => ['path' => __DIR__.'/app/controllers'] ] ]); //This is a middleware mapping "module", "controller" and "action" GET-values to //ServerRequestInterface-attributes $app->append(function($req, $res, $next) { $params = $req->getQueryParams(); $module = isset($params['module']) ? $params['module'] : null; $controller = isset($params['controller']) ? $params['controller'] : null; $action = isset($params['action']) ? $params['action'] : null; if ($module) $req = $req->withAttribute('module', $module); if ($controller) $req = $req->withAttribute('controller', $controller); if ($action) $req = $req->withAttribute('action', $action); return $next($req, $res); }); //Append our dispatcher middleware $app->append(Dispatcher::class); //Display the app $app->display();
现在您可以通过请求 index.php?module=admin&action=edit
来调用 Admin\IndexController
的 editAction
请注意,所有值都是完全可选的。
ServerRequestInterface 属性
以下属性由调度器处理
module
(默认:null
)
告诉调度器在哪个命名空间中查找控制器。在任何情况下都会添加 controller.nameSpace
选项。
controller
(默认:index
)
告诉调度器加载哪个控制器。将 my-blog
解析为 MyBlogController
以下属性由控制器处理
action
(默认:index
)
告诉控制器调用哪个操作。将 edit-user
解析为 editUserAction
如果有 getEditUserAction
方法,那么它只会监听 GET
请求。对于 POST
请求也是一样,使用 postEditUserAction
。不添加前缀将处理所有请求方法。
id
(默认:null)
指定传递给操作的第一个参数。允许的值是数值和规范字符串(如 some-user-name
)
format
(默认:html)
指定结果应该以何种格式出现。这通常等于调用 URI 的文件扩展名(如 /some-file.xml
将产生格式 xml
)
此格式将由某种输出格式化器/渲染器使用。
处理 404 错误
如果没有合适的控制器/它没有扩展正确的类/输入不正确等。
这些都是 tale-controller 检查的内容。在任何类型的失败情况下,控制权将传递给下一个中间件。
处理 404 简单地添加一个返回 404 错误的 "end" 中间件
$app->append(Dispatcher::class) ->append(function($req, $res) { $res->getBody()->write('<h1>404 - Not found!</h1>'); return $res->withStatus(404); });
简化事情
此模块专门设计为与 Tale\Router
一起工作。您可以使用它独立运行,但这需要额外的工作(但仍然非常酷!)
以下是一个示例,通过 composer 安装 talesoft/tale-router
env.json
{ "middlewares": ["Tale\\Router"], "routes": { "/blog/:action?/:id?": "My\\Controller\\BlogController", "/:controller?/:action?/:id?.:format?": "Tale\\Controller\\Dispatcher" }, "controller": { "nameSpace": "My\\Controller", "loader": { "path": "{{path}}/app/controllers" } } } ```php **index.php** ```php use Tale\App; $app = new App(['path' => __DIR__]); $app->display();
配置选项
所有配置选项。
controller.defaultModule The default module to use (Default: null)
controller.defaultController The default controller to use (Default: index)
controller.defaultAction The default action to use (Default: index)
controller.defaultId The default ID to use (Default: null)
controller.defaultFormat The default format to use (Default: html)
controller.nameSpace The namespace where controllers reside in (Default: null)
controller.modules A map [module-name => namespace] for module mapping
controller.controllerPattern The pattern for controllers (Default: %sController)
controller.controllerInflection How to inflect the controller name (Default: [Tale\Inflector, camelize]
controller.actionPattern The pattern for actions (Default: %sAction)
controller.actonInflection How to inflect the action name (Default: [Tale\Inflector, variablize]
controller.getActionPattern The pattern for GET actions (Default: get%sAction)
controller.getActonInflection How to inflect the GET action name (Default: [Tale\Inflector, camelize]
controller.postActionPattern The pattern for POST actions (Default: post%sAction)
controller.postActonInflection How to inflect the POST action name (Default: [Tale\Inflector, camelize]
controller.loader.enabled Enable an auto-loader for controllers (Default: true)
controller.loader.path The path for controller classes (Default: getcwd()/controllers)
controller.loader.pattern The pattern for controller loading (Default: %s.php)
使用多个调度器
使用多个调度器与扩展调度器一样简单。您可以设置一个选项命名空间来加载不同的配置值。
class FirstDispatcher { public function getOptionNameSpace() { return 'firstDispatcher'; } } class SecondDispatcher { public function getOptionNameSpace() { return 'secondDispatcher'; } } $app->get(Router::class) ->all('/:controller?/:action?', FirstDispatcher::class) ->all('/sub-module/:controller?/:action?', SecondDispatcher::class); $app->display();