Skip to content

Instantly share code, notes, and snippets.

@epixa
Created December 8, 2014 22:09
Show Gist options
  • Save epixa/d0e11ffc7243848578ee to your computer and use it in GitHub Desktop.
Save epixa/d0e11ffc7243848578ee to your computer and use it in GitHub Desktop.
<?php
// A traditional route in slim:
$app->get('/foo/:id', someMiddleware, function($id) use ($app) {
$app->response->headers->set('x-custom-header', 'foo');
$app->render('foo.php', ['id' => $id]);
});
// This is a very convenient pattern for small apps that can not only
// declare but also define all routes in a single file, but it has some
// drawbacks for larger apps:
// 1. Every routing function must close over $app, since $app is the
// only way to interact with request/response in any capacity
// 2. Routes cannot be autoloaded since they are just functions
// 3. All middleware and routing functions used anywhere must be
// defined on every request
// 4. Cannot easily reuse common behaviors throughout routes since they
// are just anonymous functions
// 5. Route functions are encouraged to be heavily coupled to slim
//
// The nice thing about slim is that the conventions it encourages are
// really convenient for many types of apps, but you also aren't required
// to follow those conventions. Many MVC frameworks represent controllers
// as literal classes that have individual methods (usually called actions)
// that can be tied to route definitions. In addition to organizing common
// routing behaviors, this sort of implementation allows routes to be defined
// via configuration and then autoloaded as the request dictates.
//
// So with a small amount of effort, you could define the prior example as:
$router->route('GET /', 'FooCtrl@foo')->with('someMiddleware');
class FooCtrl
{
use Renderable;
public function foo($id, $request, $response) {
$response->headers->set('x-custom-header', 'foo');
$this->render('foo', ['id' => $id]);
}
}
// Because slim is small and flexible, it is possible to use controllers and
// actions in a slim app without a bunch of hackery. You can even make your
// controllers and actions completely decoupled from slim itself, which
// promotes testability and portability. This is what I accomplished, more or
// less, with the SDO library in https://github.com/epixa/scheduled-do
//
// It's not perfect; it was mostly just a rough prototype, but it is tested
// and it wouldn't take a ton of work to make it completely reusable on any
// existing or new slim app. These are the things it does right now:
// 1. Routes are configured in a separate file without having to actually
// load/define all of the corresponding middleware and routing functions.
// 2. Routes are powered by actions (methods) on controllers (classes)
// 3. Controllers do not need to extend a base class, so no required coupling
// to slim itself
// 4. Middleware can be configured on a route-by-route basis and only be
// loaded when they match the current request
// 5. Dependency injection via service locator, which can be any service
// container you choose that implements that container-interop interface
// (the scheduled-do app itself uses php-di)
//
// So basically, the library provides some mechanisms that can help organize
// larger projects when you still ultimately want slim running under the hood.
//
// If I were to finish it to be released as a stand-alone open source project,
// I'd appreciate any and all feedback. I'd like to know what specific problems
// people have faced when using slim for larger projects.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment