Skip to content

Commit

Permalink
Add support to extend a service definition.
Browse files Browse the repository at this point in the history
  • Loading branch information
MontealegreLuis committed Jun 16, 2015
1 parent dc8c878 commit 3145df8
Show file tree
Hide file tree
Showing 18 changed files with 365 additions and 214 deletions.
6 changes: 6 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -30,3 +30,9 @@ $ php bin/phpunit --testdox
## License

This package is released under the MIT License.

## Documentation

The documentations is available at [http://comphppuebla.github.io/slim-modules/][1]

[1]: http://comphppuebla.github.io/slim-modules/
2 changes: 1 addition & 1 deletion docs/argument-converters.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ application arguments will be passed by default.

## Modifying arguments

You can pass an anonymous function to the `ControllerResolver` in order to modify the
You can pass an anonymous function to the `Resolver` in order to modify the
arguments passed to your controller. Suppose for instance that your method
`Modules\ProductCatalog\Controllers\ProductController::showProductForm` does not need
the request argument. You could remove it by registering your route the following way:
Expand Down
25 changes: 11 additions & 14 deletions docs/controller-providers.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,12 @@ In order to group the routes of your module in a single class, you need to imple
namespace Modules\ProductCatalog;

use ComPHPPuebla\Slim\ControllerProvider;
use ComPHPPuebla\Slim\ControllerResolver;
use ComPHPPuebla\Slim\Resolver;
use Slim\Slim;

class ProductCatalogControllers implements ControllerProvider
{
public function register(Slim $app, ControllerResolver $resolver)
public function register(Slim $app, Resolver $resolver)
{
$app->get('/catalog/product/edit/:id', $resolver->resolve(
$app, 'catalog.product_controller:showProductForm'
Expand All @@ -25,7 +25,7 @@ class ProductCatalogControllers implements ControllerProvider
}
```

The `ControllerResolver` class resolves the controller, method, and arguments to be
The `Resolver` class resolves the controller, method, and arguments to be
used when Slim matches the route being defined. It works the following way:

* It splits the string with the format `controller_key:method`, looking for the
Expand All @@ -35,10 +35,10 @@ use the `method` part to build a valid `callable`.
generates a function, instead of instantiating the object (giving the same effect as
if you were using `$app->container->protect`). This function will create the
controller, and it will pass the original route's arguments, the request
and the application itself as the 2 last arguments to your controller method.
and the Slim application as arguments to your controller method.
* Once the arguments are resolved it will execute the method.

Let's suppose you have the following controller:
Let's suppose the controller you registered in your provider is as follows:

```php
namespace Modules\ProductCatalog\Controllers;
Expand All @@ -60,7 +60,6 @@ class ProductController
$this->catalog = $catalog;
}


public function showProductForm($productId, Request $request, Slim $app)
{
if (!$product = $this->catalog->productOf($productId)) {
Expand All @@ -73,27 +72,25 @@ class ProductController
public function updateProductInformation(Request $request)
{
if ($this->form->isValid($request->params()) {
$productInformation = $this->form->getValues();
$product = $this->catalog->productOf($productInformation['id']);
$product->update($productInformation);
$product = $this->catalog->productOf($this->form->getProductId());
$product->update($this->form->getValues());
$this->catalog->update($product);
}
// Render the form with the errors
}
}
```

In order to add your controllers to your application you would register them in the
`public/index.php` file.
In order to add your controller to your application you would register it in your
`index` file.

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

/* Register your services first */

$services = new Modules\ProductCatalog\ProductCatalogControllers();
$services->register($app, new ComPHPPuebla\Slim\ControllerResolver());

$controllers = new Modules\ProductCatalog\ProductCatalogControllers();
$controllers->register($app, new ComPHPPuebla\Slim\Resolver());

$app->run();
```
7 changes: 3 additions & 4 deletions docs/grouping-definitions.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@ and add all your modules service providers in the `init` method by calling the m
namespace Application;

use ComPHPPuebla\Services;
use Modules\ProductCatalog\ProductCatalogServices;

class ApplicationServices extends Services
{
Expand All @@ -37,7 +36,6 @@ controllers in the `init` method (which is called automatically).
namespace Application;

use ComPHPPuebla\Slim\Controllers;
use Modules\ProductCatalog\ProductCatalogControllers;

class ApplicationControllers extends Controllers
{
Expand All @@ -55,11 +53,12 @@ Then your `index.php` file would only need:

```php
$app = new Slim\Slim();
$resolver = new ComPHPPuebla\Slim\Resolver();

$services = new Application\ApplicationServices($parameters);
$services = new Application\ApplicationServices($resolver, $parameters);
$services->configure($app);

$controllers = new Application\ApplicationControllers();
$controllers = new Application\ApplicationControllers($resolver);
$controllers->register($app);

$app->run();
Expand Down
2 changes: 1 addition & 1 deletion docs/installation.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,5 +3,5 @@
Using composer

```bash
$ composer require comphppuebla/slim-modules:~1.0@dev
$ composer require comphppuebla/slim-modules
```
74 changes: 49 additions & 25 deletions docs/service-providers.md
Original file line number Diff line number Diff line change
@@ -1,32 +1,30 @@
# Service providers

You can register the services of your module in a single class implementing
`ComPHPPuebla\Slim\ServiceProvider`.
You can package your module's services definitions in a single class implementing
`ComPHPPuebla\Slim\ServiceProvider` interface.


For instance, suppose you have a product catalog module that is part of small
application.
Suppose you have a product catalog module that is part of a small application.

```php
namespace Modules\ProductCatalog;

use ComPHPPuebla\Slim\ServiceProvider;
use Modules\ProductCatalog\Forms\ProductInformationForm;
use ComPHPPuebla\Slim\Resolver;

class ProductCatalogServices implements ServiceProvider
{
/**
* Register all your module services as usual
*/
public function configure(Slim $app)
public function configure(Slim $app, Resolver $resolver, array $parameters = [])
{
$this->container->singleton(
$app->container->singleton(
'catalog.product_repository',
function() use ($app) {
return new Catalog($app->container->get('dbal.connection'));
}
);
$this->container->singleton(
$app->container->singleton(
'catalog.product_controller',
function() use ($app) {
return new ProductController(
Expand All @@ -40,15 +38,14 @@ class ProductCatalogServices implements ServiceProvider
}
```

In order to use it in your application you would register this services in your
`public/index.php` file.
Once you have your `ServiceProvider` definition you can configure your Slim application
to use your module's services.

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

$services = new Modules\ProductCatalog\ProductCatalogServices();
$services->configure($app);

$services->configure($app, new ComPHPPuebla\Slim\Resolver());

$app->run();
```
Expand All @@ -60,31 +57,28 @@ As shown in the following example:

```php
use ComPHPPuebla\Slim\ServiceProvider;
use ComPHPPuebla\Slim\Resolver;
use Slim\Slim;
use Twig_Loader_Filesystem as Loader;
use Twig_Environment as Environment;

class TwigServiceProvider implements ServiceProvider
{
/**
* @param Slim $app
* @param array $parameters
*/
public function configure(Slim $app, array $parameters = [])
public function configure(Slim $app, Resolver $resolver, array $parameters = [])
{
$app->container->singleton('loader', function () {
$app->container->singleton('twig.loader', function () {
return new Loader($parameters['loader_paths']);
});
$app->container->singleton('twig', function () use ($app) {
$app->container->singleton('twig.environment', function () use ($app) {
return new Environment($app->container->get('loader'), $parameters['options']);
});
}
}
```

Note that the interface allows you to pass parameters to your services, you can
pass values like paths, and other configuration settings that you don't want to
hard-code in your providers.
Note that the interface allows you to pass parameters to your services. You can
pass values like filesystem paths, and other configuration settings that you
don't want to hard-code in your providers.

The following is an example of what kind of values you would pass to your provider.
They are still hard-coded to simplify the example, but this values should come from
Expand All @@ -96,7 +90,7 @@ $app = new Slim\Slim();
/* other providers.. */

$twig = new TwigServiceProvider();
$twig->configure($app, [
$twig->configure($app, new Resolver(), [
'loader_paths' => 'application/templates',
'options' => [
'cache' => 'var/cache/twig',
Expand All @@ -108,4 +102,34 @@ $twig->configure($app, [
/* your modules... */

$app->run();
```
```

## Extending services

If you have used Twig, you will know it is a common use case to register extensions.
In this case you will need to extend a service definition, i. e. take the original
service and modify it. Suppose our module needs to register its own Twig extension.
You would have to use the `Resolver` and call its `extend` method. You will need to
pass your Slim application, the original service key, and a callable to modify the
original service as arguments. The callable will receive the original service object,
followed by your Slim application as its arguments.

```php
use ComPHPPuebla\Slim\ServiceProvider;
use ComPHPPuebla\Slim\Resolver;
use Slim\Slim;
use Twig_Environment as Environment;

class ProductCatalogServices implements ServiceProvider
{
public function configure(Slim $app, Resolver $resolver, array $parameters = [])
{
/* More service definitions... */
$resolver->extend($app, 'twig.environment', function(Environment $twig, Slim $app) {
$twig->addExtension(new MyTwigExtension());

return $twig;
});
}
}
```
4 changes: 2 additions & 2 deletions phpunit.xml
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,10 @@
<phpunit
colors="true"
verbose="true"
bootstrap="./tests/bootstrap.php">
bootstrap="vendor/autoload.php">

<testsuites>
<testsuite name="integration">
<testsuite name="all">
<directory>tests</directory>
</testsuite>
</testsuites>
Expand Down
4 changes: 2 additions & 2 deletions src/ControllerProvider.php
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ interface ControllerProvider
* Register your controllers here
*
* @param Slim $app
* @param ControllerResolver $resolver
* @param Resolver $resolver
*/
public function register(Slim $app, ControllerResolver $resolver);
public function register(Slim $app, Resolver $resolver);
}
35 changes: 0 additions & 35 deletions src/ControllerResolver.php

This file was deleted.

12 changes: 6 additions & 6 deletions src/Controllers.php
Original file line number Diff line number Diff line change
Expand Up @@ -12,19 +12,19 @@

class Controllers
{
/** @var RouteProvider[] */
/** @var ControllerProvider[] */
private $providers;

/** @var ControllerResolver */
/** @var Resolver */
protected $resolver;

/**
* @param ControllerResolver $resolver
* @param Resolver $resolver
*/
public function __construct(ControllerResolver $resolver = null)
public function __construct(Resolver $resolver)
{
$this->providers = [];
$this->resolver = $resolver ?: new ControllerResolver();
$this->resolver = $resolver;
}

/**
Expand Down Expand Up @@ -54,7 +54,7 @@ public function register(Slim $app)
{
$this->init();

/** @var RouteProvider $provider */
/** @var ControllerProvider $provider */
foreach ($this->providers as $provider) {
$provider->register($app, $this->resolver);
}
Expand Down
Loading

0 comments on commit 3145df8

Please sign in to comment.