Skip to content
This repository has been archived by the owner on Jan 29, 2020. It is now read-only.

Commit

Permalink
Merge branch 'hotfix/239'
Browse files Browse the repository at this point in the history
Close #239
  • Loading branch information
weierophinney committed Dec 22, 2015
2 parents 6be6281 + 08d5228 commit 37a3618
Show file tree
Hide file tree
Showing 4 changed files with 162 additions and 2 deletions.
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@ Fifth release candidate.
- [#238](https://github.com/zendframework/zend-expressive/pull/238) adds a
cookbook recipe detailing how to handle serving an Expressive application from
a subdirectory of your web root.
- [#239](https://github.com/zendframework/zend-expressive/pull/239) adds a
cookbook recipe detailing how to create modular Expressive applications.

### Deprecated

Expand Down
3 changes: 2 additions & 1 deletion doc/book/cookbook/bookdown.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
{"Setting custom 404 page handling": "custom-404-page-handling.md"},
{"Registering custom view helpers when using zend-view": "using-custom-view-helpers.md"},
{"Using zend-form view helpers": "using-zend-form-view-helpers.md"},
{"Using Expressive from a subdirectory": "using-a-base-path.md"}
{"Using Expressive from a subdirectory": "using-a-base-path.md"},
{"Building modular applications": "modular-layout.md"}
]
}
157 changes: 157 additions & 0 deletions doc/book/cookbook/modular-layout.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,157 @@
# How can I make my application modular?

Zend Framework 2 applications have a concept of modules, independent units that
can provide configuration, services, and hooks into its MVC lifecycle. This
functionality is provided by zend-modulemanager.

While zend-modulemanager could be used with Expressive, we suggest another
approach: modules that are based only on configuration. This powerful approach
doesn't affect performance, and offers extensive flexibility: each module can
provide its own services (with factories), default configuration, and routes.

This cookbook will show how to organize modules using
[mtymek/expressive-config-manager](https://github.com/mtymek/expressive-config-manager),
a lightweight library that aggregates and merges configuration, optionally caching it.

## Install the configuration manager

The configuration manager is available in Packagist:

```bash
$ composer require mtymek/expressive-config-manager
```

## Generate your config

The default Expressive skeleton installs a `config/config.php` file, which
aggregates all configuration. When using the configuration manager, you will
need to replace the contents of that file with the following code:

```php
<?php

use Zend\Expressive\ConfigManager\ConfigManager;
use Zend\Expressive\ConfigManager\PhpFileProvider;

$configManager = new ConfigManager([
new PhpFileProvider('config/autoload/{{,*.}global,{,*.}local}.php'),
]);

return new ArrayObject($configManager->getMergedConfig());
```

If you open your application in a browser, it should still work in exactly the
same way as it was before. Now you can start adding your modules.

## First module

`ConfigManager` does not force you to use any particular structure for your
module; its only requirement is to expose default configuration using a "config
provider", which is simply an invokable class that returns a configuration
array.

For instance, this is how your module could provide its own routes:

```php
namespace App;

class AppConfig
{
public function __invoke()
{
return [
'routes' => [
[
'name' => 'api.list-transactions',
'path' => '/api/transactions',
'middleware' => App\Action\ListTransactionsAction::class,
'allowed_methods' => ['GET'],
],
[
'name' => 'api.refund-transaction',
'path' => '/api/refund',
'middleware' => App\Action\RefundAction::class,
'allowed_methods' => ['POST'],
],
],
];
}
}
```

## Enabling the module

Finally, you can enable your module by adding a reference to your config class
within the arguments of the `ConfigManager` constructor in the `config/config.php`
file:

```php
$configManager = new ConfigManager([
App\AppConfig::class,
new PhpFileProvider('config/autoload/{{,*.}global,{,*.}local}.php'),
]);
```

## Caching configuration

In order to provide configuration caching, two things must occur:

- First, you must define a `config_cache_enabled` key in your configuration
somewhere.
- Second, you must pass a second argument to the `ConfigManager`, the location
of the cache file to use.

The `config_cache_enabled` key can be defined in any of your configuration
providers, including the autoloaded configuration files. We recommend defining
them in two locations:

- `config/autoload/global.php` should define the value to `true`, as the
production setting.
- `config/autoload/local.php` should also define the setting, and use a value
appropriate to the current environment. In development, for instance, this
would be `false`.

```php
// config/autoload/global.php

return [
'config_cache_enabled' => true,
/* ... */
];

// config/autoload/local.php

return [
'config_cache_enabled' => false, // <- development!
/* ... */
];
```

You would then alter your `config/config.php` file to add the second argument.
The following example builds on the previous, and demonstrates having the
`AppConfig` entry enabled. The configuration will be cached to
`data/config-cache.php` in the application root:

```php
$configManager = new ConfigManager([
App\AppConfig::class,
new PhpFileProvider('config/autoload/{{,*.}global,{,*.}local}.php'),
], 'data/config-cache.php');
```

When the configuration cache path is present, if the `config_cache_enabled` flag
is enabled, then configuration will be read from the cached configuration,
instead of parsing and merging the various configuration sources.

## Final notes

This approach may look simple, but it is flexible and powerful:

- You pass a list of config providers to the `ConfigManager` constructor.
- Configuration is merged in the same order as it is passed, with later entries
having precedence.
- You can override module configuration using `*.global.php` and `*.local.php` files.
- If cached config is found, `ConfigManager` does not iterate over provider list.

For more details, please refer to the
[Config Manager Documentation](https://github.com/mtymek/expressive-config-manager#expressive-configuration-manager).
2 changes: 1 addition & 1 deletion mkdocs.yml
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ pages:
- { Helpers: [{ Introduction: helpers/intro.md }, { UrlHelper: helpers/url-helper.md }, { ServerUrlHelper: helpers/server-url-helper.md }] }
- { Emitters: emitters.md }
- { Examples: usage-examples.md }
- { Cookbook: [{ 'Prepending a common path to all routes': cookbook/common-prefix-for-routes.md }, { 'Route-specific middleware pipelines': cookbook/route-specific-pipeline.md }, { 'Setting custom 404 page handling': cookbook/custom-404-page-handling.md }, { 'Registering custom view helpers when using zend-view': cookbook/using-custom-view-helpers.md }, { 'Using zend-form view helpers': cookbook/using-zend-form-view-helpers.md }, { 'Using Expressive from a subdirectory': cookbook/using-a-base-path.md }] }
- { Cookbook: [{ 'Prepending a common path to all routes': cookbook/common-prefix-for-routes.md }, { 'Route-specific middleware pipelines': cookbook/route-specific-pipeline.md }, { 'Setting custom 404 page handling': cookbook/custom-404-page-handling.md }, { 'Registering custom view helpers when using zend-view': cookbook/using-custom-view-helpers.md }, { 'Using zend-form view helpers': cookbook/using-zend-form-view-helpers.md }, { 'Using Expressive from a subdirectory': cookbook/using-a-base-path.md }, { 'Building modular applications': cookbook/modular-layout.md }] }
- { 'Expressive Projects': expressive-projects.md }
site_name: zend-expressive
site_description: 'zend-expressive: PSR-7 Middleware Microframework'
Expand Down

0 comments on commit 37a3618

Please sign in to comment.