Folks, my question is about how to design clean and readable files/classes to handle the routes. If you take a look at any example on the internet, the simplest way is to put many of the following into index.php :
$app->get("/pattern", function( $request, $response, $args){ //the whole code here } );
But that does not look clean to me. Imagine you have many routes, an API , middlewares and so on. Not to mention all configuration (errorHandlers and many other container settings).
I would like to know if some of you have designed something to solve this problem. My personal approach by now is:
index.php:
- I’m coding all config in here (declare container variables for Twig, Monolog, Erro handling, not too much code)
- include routes files, using the following strategy:
# index.php
// configs up here
/*
* Routes
*/
//some "core" routes
require_once "routes.php";
//routes for auth like, /login, /logout and declare Middleware that have to do with authentication/authorization
require_once "routes-auth.php";
//routes I use from a PHP shell
require_once "routes-cli.php";
//I have not created one, but is intended to put all API routes here, maybe one file per version:
//routes-api_v1.php , routes-api_v2.php ...
require_once "routes-api.php";
//all other middlewares
require_once "routes-middleware.php";
//ends with:
$app->run();
But it is not enough for me. the next step I use is to implement the route cycle like these:
# some of the routes-xxxx.php looks like:
Route::get('/', 'Core\ctrl\CoreController:home')->setName('homePage');
Route::get('/hello[/{name}]', 'Core\ctrl\CoreController:sayHello')->setName('hello');
Route::get('/protected', 'Core\ctrl\CoreController:callProtectedResource')->setName('protected');
# I stactified the call based on https://github.com/silentworks/madmin-api , from Andrew Smith, a Slim developer. Looks cleaner to me.
# now the call is delegated to one of the Controllers . I divide controllers by subjects, so I do not have many functions in one class
# the Core\ctrl\CoreController.php :
public static function home(SlimHttpRequest $request, SlimHttpResponse $response, $args)
{
try {
$cmd = new HomeCommand($request, $response, $args);
//the process() make it simple to reuse the same code by other function:
$cmd->process();
//the same processed data could be easily transformed to be used by Twig or JSON ajax response
$cmd->respondWithHtml();
} catch (Exception $e) {
throw $e;
}
}
# inside the HomeCommand.php
class HomeCommand extends AbstractCommand {
public function __construct(\Slim\Http\Request $request, \Slim\Http\Response $response, $args){
parent::__construct ($request, $response, $args );
}
public function process() {
$request = new MobileRequest( $this->request );
$isMobile = $request->isMobile();
$this->data = array("isMobile" => $isMobile);
// When necessary, Persistent Layer would be called from here.
//I use Doctrine, so I would call the Entity Manager here:
$em = DAO::em(); //my dao with doctrine configs
$personsDAO = $em->getRepository("dao\Person")->findBy(array(), array("name" => "ASC" );
$this->data = array("persons" => $personDAO); //now twig view can iterate over this list
return $this;
}
public function respondWithJson() {
// used to respond to Ajax calls with a JSON representation of the data
}
public function respondWithHtml() {
return App::object()->getContainer()->view->render($this->response, 'home.html', $this->data);
}
}
What do you think about this strategy? Any better ideas?
Thanks in advance,
using Slim since 2.1 release. Now migrated my projects to Slim 3.