【问题标题】:PHP Slim Framework Create ControllerPHP Slim 框架创建控制器
【发布时间】:2016-04-04 23:43:35
【问题描述】:

我正在使用 Slim 框架创建一个 API。目前我使用单个文件来创建路由并将闭包传递给它:

$app->get('/', function($req, $resp){
//Code...
})

但我意识到我的文件增长迅速。我想做的是改用控制器,所以我将有一个控制器类,只需将实例/静态方法传递给路由,如下所示

class HomeController
{
   public static function index($req, $resp){}
}

然后将函数传递给路由

$app->get('/', HomeController::index);

我试过这个,但它不起作用,我想知道是否有一种方法可以使用它来管理我的文件。

【问题讨论】:

    标签: php controller slim slim-3


    【解决方案1】:

    把控制器变成函子:

    class HomeController
    {
        public function __invoke($req, $resp) {}
    }
    

    然后像这样路由:

    $app->get('/', HomeController::class);
    

    参考,见

    【讨论】:

    • 添加控制器使用哪个文件夹?
    【解决方案2】:

    PHP 5.6 超薄 2.6.2

    require 'vendor/autoload.php';
    
    class HelloController {
        public static function index()  {
            global $app;
    
            echo "<pre>";
            var_dump($app->request);
            echo "</pre>";
        }
    }
    
    $app = new \Slim\Slim();
    $app->get('/', 'HelloController::index');
    $app->run();
    

    更新: PHP 5.6 Slim 3.0.0

    require 'vendor/autoload.php';
    
    class HelloController {
        public static function hello(\Slim\Http\Request $req, \Slim\Http\Response $response, $args)  {
            echo "<pre>";
            var_dump($args);
            echo "</pre>";
        }
    }
    
    $app = new \Slim\App();
    $app->get('/hello/{name}', 'HelloController::hello');
    $app->run();
    

    Slim 3.0 中基于类的路由的问题是访问$this/$app。我想你需要使用global $app 来访问它。

    在我的宠物项目中,我使用带有require_once 的路由组。类似的东西

    $app->group('/dashboard', function () {
        $this->group('/auctions', function () use ($app){
            require_once('routes/dashboard/auctions.php');
        });
        $this->group('/rss', function () {
            require_once('routes/dashboard/rss.php');
        });
        $this->group('/settings', function () {
            require_once('routes/dashboard/settings.php');
        });
    });
    

    看起来不像纯类那样美观,但可以正常工作,无需额外编码即可访问所有功能。

    【讨论】:

    • 如果您继承 slim\application 并在其中包含路由文件,那么您可以在整个路由配置中一致地使用 $this。我在这里添加了一个示例stackoverflow.com/questions/41981048/… 另外,可以有一个将 Application 作为构造函数依赖项的路由配置类
    • @Roman 当您使用正确的命名空间并使用 composer 时,您不需要自己调用 require(),因为 autoload.php 会为您完成。
    【解决方案3】:

    将控制器用作对象的流畅且简短的方式(不是静态方式)

    在 index.php 中

    namespace MyApp;
    
    use \Psr\Http\Message\ServerRequestInterface as Request;
    use \Psr\Http\Message\ResponseInterface as Response;
    
    require __DIR__ . '/../vendor/autoload.php';
    
    $app->get('/myroute', [new Controller\MyClass, 'get']); // <=== that is pretty short  and neat
    $app->post('/myroute', [new Controller\MyClass, 'post']);
    $app->map(['GET', 'POST'], '/myotherrout', [new Controller\MyOtherClass, 'run']);
    

    在控制器/MyClass 中:

    namespace MyApp\Controller;
    
    class MyClass{
    
        public function __construct(){
           //some code
        }
    
        public function get(\Slim\Http\Request $request, \Slim\Http\Response $response, $args = []) {
           //some super foobar code
        }
    
        public function post(\Slim\Http\Request $request, \Slim\Http\Response $response, $args = []) {
           //some other code
        }
    

    Controller\MyClass 是通过使用 PSR 自动加载来解决的

    在控制器/MyOtherClass 中:

    namespace MyApp\Controller;
    
    class MyOtherClass{
    
        public function __construct(){
           //some code
        }
    
        public function run(\Slim\Http\Request $request, \Slim\Http\Response $response, $args = []) {
           //some amazing foobar code
        }
    

    【讨论】:

    • 确实非常好!谢谢!您如何将服务直接注入控制器而不使用它通过容器?
    • 虽然这可行,但控制器实例的创建应该在依赖容器注册内完成
    【解决方案4】:

    这是一个例子:

    控制器

    <?php
    
    use Psr\Http\Message\ServerRequestInterface;
    use Psr\Http\Message\ResponseInterface;
    use Psr\Log\LoggerInterface;
    
    /**
     * @property LoggerInterface $logger;
     */
    class Controller
    {
        /**
         * @var LoggerInterface
         */
        protected $logger
    
        /**
         * @param LoggerInterface $logger
         */
        public function __construct($logger)
        {
            $this->logger = $logger;
        }
    
        public function action(ServerRequestInterface $request, ResponseInterface $response, $args=[])
        {
            $this->logger->info((string)$request->getUri());
            /* some actions */
            return $response;
        }
    }
    

    应用

    <?php
    
    use Slim\App;
    use Slim\Container;
    use Psr\Container\ContainerInterface;
    
    $autoloader = require(__DIR__.'/vendor/autoload.php');
    
    $container = new Container();
    
    $container['logger'] = function($container) {
        return new Logger();
    }
    
    $container['some.controller'] = function ($container) {
        /**
         * @var ContainerInterface $container
         */
        $logger = $container->get('logger');
    
        return new Controller($logger);
    };
    
    $app = new App($container);
    $app->get('/some/route', 'some.controller:action');
    
    $app->run();
    

    利润!

    这个方法在文档click me中有描述

    【讨论】:

    【解决方案5】:

    Nikic 的 Fast Route 是一个非常小的路由器,因此删除了较大框架的一些细节。这是一个基本的解决方案:

    routes.php

    use \Psr\Http\Message\ServerRequestInterface as Request;
    use \Psr\Http\Message\ResponseInterface as Response;
    
    $app->get('/', function($req, $resp, $args) use ($app){return FooBar::asdf($app, $req, $resp);});
    

    控制器 使用 \Psr\Http\Message\ServerRequestInterface 作为请求; 使用 \Psr\Http\Message\ResponseInterface 作为响应;

    class FooBar{
        static public function asdf(Slim\App $app, Request $req, Response $resp, $args = [])
        {
            return $resp->withJson(['asf']);
        }
    }
    

    【讨论】:

      猜你喜欢
      • 2019-01-11
      • 2015-04-30
      • 2015-08-04
      • 1970-01-01
      • 1970-01-01
      • 2017-12-12
      • 2017-10-11
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多