talesoft/tale-controller

适用于 talesoft/tale-app 的控制器中间件

0.1 2016-02-29 23:32 UTC

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\IndexControllereditAction

请注意,所有值都是完全可选的。

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();