Skip to content

Commit

Permalink
Group middleware registration.
Browse files Browse the repository at this point in the history
  • Loading branch information
MontealegreLuis committed Aug 11, 2015
1 parent b32446b commit 8589ed4
Show file tree
Hide file tree
Showing 6 changed files with 260 additions and 5 deletions.
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ It provides the following features:
* Group your service definitions in service providers classes
* Group and configure your controllers in controller providers classes
* Group all your application controllers and services in single classes
* Register all your application middleware in a single class

## Tests

Expand Down
3 changes: 3 additions & 0 deletions couscous.yml
Original file line number Diff line number Diff line change
Expand Up @@ -24,3 +24,6 @@ menu:
grouping_definitions:
text: Grouping definitions
relativeUrl: docs/grouping-definitions.html
middleware:
text: Application middleware
relativeUrl: docs/middleware.html
104 changes: 104 additions & 0 deletions docs/middleware.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
# Application middleware

Slim implements a version of the Rack protocol, therefore it can have middleware
that may inspect, or modify the application environment, request, and response
before and/or after the Slim application is invoked.

You can register all your application middleware in a single place. You only
need to extend the class `ComPHPPuebla\Slim\MiddlewareLayers` and add all your
middleware in the `init` method by calling the method `add`.

Suppose you have a middleware that logs the requests, matched routes and responses
of your application. You would have to register it the following way.

```php
namespace Application;

use Slim\Helper\Set;
use ComPHPPuebla\MiddlewareLayers;

class ApplicationMiddleware extends MiddlewareLayers
{
/**
* Add the middleware for your application here
*/
protected function init(Set $container)
{
$this
->add(new RequestLoggingMiddleware())
;
}
}
```

## Using the container

Suppose you want to use dependency injection for your middleware in order to
control what logger your application should use, instead of simply using Slim's
logger.

You could register a [Monolog][1] logger in a service provider.

```php
namespace Application;

use ComPHPPuebla\Slim\Resolver;
use ComPHPPuebla\Slim\ServiceProvider;
use Monolog\Handler\StreamHandler;
use Monolog\Logger;
use Slim\Slim;

class MonologServiceProvider implements ServiceProvider
{
public function configure(Slim $app, Resolver $resolver, array $options = [])
{
$app->container->singleton(
'logger',
function () use ($app, $options) {
$logger = new Logger($options['monolog']['channel']);
$logger->pushHandler(new StreamHandler(
$options['monolog']['path'], Logger::DEBUG
));

return $logger;
}
);
}
}
```

And then retrieve the object inside the `init` method through the container.

```php
protected function init(Set $container)
{
$this
->add(new RequestLoggingMiddleware($container->get('logger'))
;
}
```

Alternatively, you could register the middleware class inside a service provider
and simply retrieve it from the container.

```php
protected function init(Set $container)
{
$this
->add($container->get('slim.middleware.request_logger')
;
}
```

Then your `index.php` file would only need:

```php
$app = new Slim\Slim();

$middleware = new Application\ApplicationMiddleware();
$middleware->configure($app);

$app->run();
```

[1]: https://github.com/Seldaek/monolog
10 changes: 5 additions & 5 deletions docs/service-providers.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ class ProductCatalogServices implements ServiceProvider
/**
* Register all your module services as usual
*/
public function configure(Slim $app, Resolver $resolver, array $parameters = [])
public function configure(Slim $app, Resolver $resolver, array $options = [])
{
$app->container->singleton(
'catalog.product_repository',
Expand Down Expand Up @@ -64,13 +64,13 @@ use Twig_Environment as Environment;

class TwigServiceProvider implements ServiceProvider
{
public function configure(Slim $app, Resolver $resolver, array $parameters = [])
public function configure(Slim $app, Resolver $resolver, array $options = [])
{
$app->container->singleton('twig.loader', function () {
return new Loader($parameters['loader_paths']);
return new Loader($options['loader_paths']);
});
$app->container->singleton('twig.environment', function () use ($app) {
return new Environment($app->container->get('loader'), $parameters['options']);
return new Environment($app->container->get('loader'), $options['options']);
});
}
}
Expand Down Expand Up @@ -122,7 +122,7 @@ use Twig_Environment as Environment;

class ProductCatalogServices implements ServiceProvider
{
public function configure(Slim $app, Resolver $resolver, array $parameters = [])
public function configure(Slim $app, Resolver $resolver, array $options = [])
{
/* More service definitions... */
$resolver->extend($app, 'twig.environment', function(Environment $twig) {
Expand Down
56 changes: 56 additions & 0 deletions src/MiddlewareLayers.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
<?php
/**
* PHP version 5.5
*
* This source file is subject to the license that is bundled with this package in the file LICENSE.
*
* @copyright Comunidad PHP Puebla 2015 (http://www.comunidadphppuebla.com)
*/
namespace ComPHPPuebla\Slim;

use Slim\Helper\Set;
use Slim\Middleware;
use Slim\Slim;

class MiddlewareLayers
{
/** @var array */
private $middleware = [];

/**
* Override this in subclasses to add your Slim middleware classes
*
* This method will be called at the beginning of ComPHPPuebla\Slim\MiddlewareLayers::configure
*
* @param Set $container
*/
protected function init(Set $container)
{
}

/**
* @param Middleware $middleware
* @return MiddlewareLayers
*/
public function add(Middleware $middleware)
{
$this->middleware[] = $middleware;

return $this;
}

/**
* Configure the middleware layers for your application
*
* @param Slim $app
*/
public function configure(Slim $app)
{
$this->init($app->container);

/** @var MiddlewareProvider $middleware */
foreach ($this->middleware as $middleware) {
$app->add($middleware);
}
}
}
91 changes: 91 additions & 0 deletions tests/MiddlewareLayersTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
<?php
/**
* PHP version 5.5
*
* This source file is subject to the license that is bundled with this package in the file LICENSE.
*
* @copyright Comunidad PHP Puebla 2015 (http://www.comunidadphppuebla.com)
*/
namespace ComPHPPuebla\Slim;

use PHPUnit_Framework_TestCase as TestCase;
use Slim\Helper\Set;
use Slim\Middleware;
use Slim\Slim;
use stdClass;

class FakeMiddleware extends Middleware
{
private $logger;

public function __construct($logger)
{
$this->logger = $logger;
}

public function call()
{
}
}

class FakeMiddlewareLayers extends MiddlewareLayers
{
public function init(Set $container)
{
$this->add(new FakeMiddleware($container->get('logger')));
}
}

class MiddlewareLayersTest extends TestCase
{
/** @test */
function it_should_register_middleware_to_the_given_slim_application()
{
$middleware1 = $this->getMock(Middleware::class);
$middleware2 = $this->getMock(Middleware::class);

$builder = $this->getMockBuilder(Slim::class);
$app = $builder->setMethods(['add'])->getMock();

$app
->expects($spy = $this->exactly(2))
->method('add')
->with($this->isInstanceOf(Middleware::class))
;

$middleware = new MiddlewareLayers();
$middleware
->add($middleware1)
->add($middleware2)
;

$middleware->configure($app);

$this->assertEquals(
2, $spy->getInvocationCount(), 'It should have registered 2 middleware layers'
);
}

/** @test */
function it_should_be_able_to_use_slim_container_to_build_middleware()
{
$app = new Slim();
$container = $this->getMock(Set::class);
$container
->expects($spy = $this->once())
->method('get')
->with('logger')
->willReturn($this->returnValue(new stdClass()))
;

$app->container = $container;

$middleware = new FakeMiddlewareLayers();

$middleware->configure($app);

$this->assertEquals(
1, $spy->getInvocationCount(), 'It should have retrieved the logger from the container'
);
}
}

0 comments on commit 8589ed4

Please sign in to comment.