mbarquin/slim-dynamic-routing

用于实例化和配置 Slim 框架以使用动态路由的工厂对象

1.0.1 2017-10-30 22:53 UTC

This package is not auto-updated.

Last update: 2024-09-14 19:09:29 UTC


README

使用工厂对象设置 Slim 3 动态路由

我实际上正在使用 Slim 3 进行“乐趣”应用程序的原型设计,我通常更喜欢使用动态路由,避免为每次添加新操作生成条目。我有一段代码,用于设置 Slim 3 框架路由,根据调用路由实例化控制器。我将容器 DI 传递给这个控制器,并在每个方法中获取所有需要的依赖项,但最终我总是依赖于 Container 接口。现在我重写了代码以提高其可重用性和可测试性,我实现了一个通道,通过父控制器传递依赖项,以避免这种容器依赖。

基本思想是一个工厂对象,可以实例化和设置一个 slim 应用程序,这个 slim 应用程序将准备好实例化控制器类,这允许路由向控制器注入依赖项。

安装

您可以通过以下方式安装该组件

用法

在要求自动加载后,我们可以通过静态调用请求工厂对象进行 Slim App 设置并检索一个可用的 Slim 应用程序实例。

    require __DIR__ . '/../vendor/autoload.php';
    $settings = require __DIR__ . '/../src/settings.php';

    $app = \mbarquin\SlimDR\Factory::slim()
            ->withGroup('api')
            ->withVersionGroup('v1')
            ->withContainer($settings)
            ->withNamespace('\\MyApp\\Controller')
            ->getApp();

    $app->run();

静态方法 slim() 返回工厂对象,并且每个后续调用都将返回相同的对象以继续设置过程。像 withGroup、withVersionGroup、withContainer 和 withNamespace 这样的方法都返回工厂对象本身,允许在它上面连接函数。getApp 函数最终返回一个新的 \Slim\App 对象。

  • slim(\Slim\App $app=null) 它创建并返回一个新的 Factory 实例,如果提供了 \Slim\App 作为参数,它将保留对该实例的引用(在测试过程中),以便设置此实例,而不是在调用 getApp() 时创建一个新的实例。

  • withGroup($mainGroup) 它设置主组名称,用作这些调用上的前缀,例如 http://www.myserver.com/api/controller,此函数返回工厂对象本身。如果没有设置,则路由将使用版本组或无前缀。

  • withVersionGroup($versionGroup) 它设置次要组名称,用作这些调用上的子前缀,例如 http://www.myserver.com/api/v1/controller,此函数返回工厂对象本身。如果没有设置,则路由将使用主组作为前缀 http://www.myserver.com/api/controller,或无前缀 http://www.myserver.com/controller

  • withContainer($settings) 必须设置。它用于请求工厂对象在 \Slim\App 构造函数中注入配置数组或容器。

  • withNamespace('\\MyApp\\Controller') 必须设置。它用于使用其命名空间自动加载控制器。这些控制器必须扩展 \mbarquin\SlimDR\ParentController 或实现 \mbarquin\SlimDR\ControllerInterface,如下所述。

  • getApp() 实例化并返回一个带有所有先前参数的新 \Slim\App 实例。(在测试过程中)如果在初始静态方法 slim($app) 中提供了 Slim\App 对象作为参数,则此函数将设置此实例并返回它。

现在您只需要在控制器中扩展 SlimDR ParentController,或者在自己的父控制器中实现 ControllerInterface。这种实现是为了避免 服务定位反模式,我们的控制器必须提供一种方式来沟通它们的依赖项。这样我们的控制器将不会依赖于容器,而只依赖于我们真正需要使用的服务。

Slim 将搜索和调用一个类似于调用方法名称的函数(小写),如果是一个方法 GET 调用,则控制器中将调用 get 函数。如果是通过 PUT 方法调用,Slim 将尝试在控制器上调用 put 函数。

    /**
     * Test Controller file
     * SlimDR example controller
     *
     * PHP version 5.6
     *
     *
     * @category   SlimDR
     * @package    Test
     * @subpackage Controller
     * @author     Moises Barquin Salgado <moises.barquin@gmail.com>
     * @copyright  Moises Barquin Salgado 2016
     * @version    GIT: $Id$
     */

    namespace MyApp\Controller;

    use mbarquin\SlimDR\ParentController;

    /**
     * Class test, must implements Controller interface
     * It's extended from mbarquin\SlimDR\Parentcontroller
     */
    class test extends ParentController
    {
        /**
         * Array with actions dependencies, in the form [ method => [dependencies]]
         * @var type
         */
        protected $dependencies = array(
            self::GET => array ('db', 'logger')
        );

        /**
         * GET method as controller action,
         * Params which are not request, reponse and args must be declared on
         * dependencies array.
         *
         * @param Psr\Http\Message\ServerRequestInterface $request  Request object
         * @param Psr\Http\Message\ResponseInterface      $response Reponse object
         * @param array                                   $args     Request params
         * @param \stdClass                               $db       Database object
         * @param \Monolog\Logger                         $logger   Logger object
         */
        public function get($request, $response, $args, \stdClass $db, \Monolog\Logger $logger)
        {
            print_r($args);
        }
    }

控制器受保护的属性 $dependencies 必须是一个数组,索引必须是请求方法名称(小写),并且其数组内容必须是依赖项容器的键,以便访问必要的对象。父控制器已经声明了所有这些方法名称(GET、POST、DELETE 等)作为常量,因此我们可以使用它们来定义这个数组

    $dependencies = array(
        self::POST => array('dep1', 'db', 'dep3'),
        self::GET  => array('dep1'),
        self::PUT  => array('dep3')
        ...
    );

这些依赖项必须已经注入到 DI 容器中,依赖项方法数组中的键必须是用于在容器中定位对象的键。在我们的控制器之外,必须设置 Slim 容器以完成这些依赖项。

    $container       = $app->getContainer();

    $container['db'] = function ($c) {
        $db = new stdClass();

        return $db;
    };