可以将文章内容翻译成中文,广告屏蔽插件可能会导致该功能失效(如失效,请关闭广告屏蔽插件后再试):
问题:
I am creating an API using the Slim framework. Currently I use a single file to create the route and pass a closure to it:
$app->get('/', function($req, $resp){
//Code...
})
But I realise that my file has grown rapidly. What I want to do is use controllers instead, so I will have a controller class and just pass the instance/static methods to the route, like below
class HomeController
{
public static function index($req, $resp){}
}
and then pass the function to the route
$app->get('/', HomeController::index);
I tried this, but it does not work, and I wonder if there is a way I can use it to manage my files.
回答1:
Turn the controller into a functor:
class HomeController
{
public function __invoke($req, $resp) {}
}
and then route like this:
$app->get('/', HomeController::class);
For reference, see
- http://www.slimframework.com/docs/objects/router.html#how-to-create-routes
- http://www.slimframework.com/docs/objects/router.html#route-callbacks.
回答2:
PHP 5.6
Slim 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();
Update: 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();
The problem with class based routing in Slim 3.0 is access to $this
/$app
. I think you will need to use global $app
to access it.
In my pet project I use route groups with require_once
. Something like
$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');
});
});
Looks not as beauty as could be with pure classes but works like expected with all features accessible without additional coding.
回答3:
Smooth & short way to use a controller as an object (not a static way)
in 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']);
in Controller/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
}
The Controller\MyClass is resolved through the use of PSR autoload
in Controller/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:
Here's an example:
Controller
<?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;
}
}
Application
<?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();
Profit!
This method is described in the documentation click me
回答5:
Nikic's Fast Route is a very minimal router, so some of the niceties of the bigger frameworks are removed. Here's a basic solution:
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);});
controller
use \Psr\Http\Message\ServerRequestInterface as Request;
use \Psr\Http\Message\ResponseInterface as Response;
class FooBar{
static public function asdf(Slim\App $app, Request $req, Response $resp, $args = [])
{
return $resp->withJson(['asf']);
}
}