Контроллер создания PHP Slim Framework

Я создаю API, используя фреймворк Slim. В настоящее время я использую один файл для создания маршрута и передачи ему закрытия:

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

Но я понимаю, что мой файл быстро вырос. Вместо этого я хочу использовать контроллеры, поэтому у меня будет класс контроллера, и я просто передам экземпляр/статические методы маршруту, как показано ниже.

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

а затем передать функцию маршруту

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

Я пробовал это, но это не работает, и мне интересно, есть ли способ использовать его для управления моими файлами.


person James Okpe George    schedule 30.12.2015    source источник


Ответы (5)


Превратите контроллер в функтор:

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

а затем маршрут следующим образом:

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

Для справки см.

person localheinz    schedule 31.12.2015
comment
Какая папка используется для добавления контроллера? - person Elby; 03.01.2017

Гладкий и короткий способ использования контроллера в качестве объекта (не статический способ)

в 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
    }

Контроллер\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
    }
person Cedric    schedule 06.02.2018
comment
Действительно очень приятно! Спасибо! Как бы вы внедрили службу прямо в контроллер, минуя контейнер с его помощью? - person Strnm; 10.04.2018
comment
Пока это работает, создание экземпляра контроллера должно выполняться внутри регистрации контейнера зависимостей. - person Zamrony P. Juhara; 16.04.2018

Вот пример:

Контроллер

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

Выгода!

Этот метод описан в документации нажмите я

person Ivan Dudarev    schedule 19.04.2018
comment
Я вижу, вы передаете $logger контроллеру, не должны ли вы передать контейнер? - person crafter; 13.03.2019
comment
@crafter передает контейнер контроллеру — плохая практика. см. en.wikipedia.org/wiki/Single_responsibility_principle и en.wikipedia.org/wiki/Dependency_injection - person Ivan Dudarev; 14.03.2019
comment
Я слышу тебя. Вы правы, этот контейнер слишком велик, чтобы тащить его в ваши классы. - person crafter; 15.03.2019

Fast Route от Nikic — это очень простой маршрутизатор, поэтому некоторые тонкости более крупных фреймворков удалены. Вот основное решение:

маршруты.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']);
    }
}
person user3791372    schedule 16.07.2017

person    schedule
comment
Если вы создадите подкласс slim\application и включите туда файл маршрута, вы сможете последовательно использовать $this во всей конфигурации маршрута. Я добавил здесь пример stackoverflow.com/questions/41981048/ Кроме того, можно было бы иметь класс конфигурации маршрута, который принимает приложение как зависимость конструктора - person malte; 03.02.2017
comment
@Roman, когда вы используете правильное пространство имен и используете композитор, вам не нужно вызывать require() самостоятельно, потому что autoload.php сделает это за вас. - person Zamrony P. Juhara; 16.04.2018