|
| 1 | +# Command Line Tooling |
| 2 | + |
| 3 | +Expressive offers a number of tools for assisting in project development. This |
| 4 | +page catalogues each. |
| 5 | + |
| 6 | +## Development Mode |
| 7 | + |
| 8 | +- Since 2.0. |
| 9 | + |
| 10 | +The package [zfcampus/zf-development-mode](https://github.com/zfcampus/zf-development-mode) |
| 11 | +provides a simple way to toggle in and out of _development mode_. Doing so |
| 12 | +allows you to ship known development-specific settings within your repository, |
| 13 | +while ensuring they are not enabled in production. The tooling essentially |
| 14 | +enables optional, development-specific configuration in your application by: |
| 15 | + |
| 16 | +- Copying the file `config/development.config.php.dist` to |
| 17 | + `config/development.config.php`; this can be used to enable |
| 18 | + development-specific modules or settings (such as the `debug` flag). |
| 19 | +- Copying the file `config/autoload/development.local.php.dist` to |
| 20 | + `config/autoload/development.local.php`; this can be used to provide local |
| 21 | + overrides of a number of configuration settings. |
| 22 | + |
| 23 | +The package provides the tooling via `vendor/bin/zf-development-mode`. If you |
| 24 | +are using the Expressive skeleton, it provides aliases via Composer: |
| 25 | + |
| 26 | +```php |
| 27 | +$ composer development-enable |
| 28 | +$ composer development-disable |
| 29 | +$ composer development-status |
| 30 | +``` |
| 31 | + |
| 32 | +Add settings to your `development.*.php.dist` files, and commit those files to |
| 33 | +your repository; always toggle out of and into development mode after making |
| 34 | +changes, to ensure they pick up in your development environment. |
| 35 | + |
| 36 | +## Modules |
| 37 | + |
| 38 | +- Since 2.0. |
| 39 | + |
| 40 | +The package [zendframework/zend-expressive-tooling](https://github.com/zendframework/zend-expressive-tooling) |
| 41 | +provides the binary `vendor/bin/expressive-module`, which allows you to create, |
| 42 | +register, and deregister modules, assuming you are using a [modular application |
| 43 | +layout](../features/modular-applications.md). |
| 44 | + |
| 45 | +> ### Adding tooling to existing applications |
| 46 | +> |
| 47 | +> If you have upgraded from Expressive 1.X, you can install |
| 48 | +> zendframework/zend-expressive-tooling via Composer: |
| 49 | +> |
| 50 | +> ```bash |
| 51 | +> $ composer require --dev zendframework/zend-expressive-tooling |
| 52 | +> ``` |
| 53 | +
|
| 54 | +For instance, if you wish to create a new module for managing users, you might |
| 55 | +execute the following: |
| 56 | +
|
| 57 | +```bash |
| 58 | +$ ./vendor/bin/expressive-module create User |
| 59 | +``` |
| 60 | +
|
| 61 | +Which would create the following tree: |
| 62 | +
|
| 63 | +```text |
| 64 | +src/ |
| 65 | + User/ |
| 66 | + src/ |
| 67 | + ConfigProvider.php |
| 68 | + templates/ |
| 69 | +``` |
| 70 | +
|
| 71 | +It would also create an autoloading rule within your `composer.json` for the |
| 72 | +`User` namespace, pointing it at the `src/User/src/` tree (and updating the |
| 73 | +autoloader in the process), and register the new module's `ConfigProvider` |
| 74 | +within your `config/config.php`. |
| 75 | +
|
| 76 | +The `register` command will take an existing module and: |
| 77 | +
|
| 78 | +- Add an autoloading rule for it to your `composer.json`, if necessary. |
| 79 | +- Add an entry for the module's `ConfigProvider` class to your |
| 80 | + `config/config.php`, if possible. |
| 81 | +
|
| 82 | +```bash |
| 83 | +$ ./vendor/bin/expressive-module register Account |
| 84 | +``` |
| 85 | +
|
| 86 | +The `deregister` command does the opposite of `register`. |
| 87 | +
|
| 88 | +```bash |
| 89 | +$ ./vendor/bin/expressive-module deregister Account |
| 90 | +``` |
| 91 | +
|
| 92 | +## Migrate to programmatic pipelines |
| 93 | +
|
| 94 | +- Since 2.0. |
| 95 | +
|
| 96 | +Starting in 2.0, we recommend using _programmatic pipelines_, versus |
| 97 | +configuration-defined pipelines. For those upgrading their applications from 1.X |
| 98 | +versions, we provide a tool that will read their application configuration and |
| 99 | +generate: |
| 100 | +
|
| 101 | +- `config/pipeline.php`, with the middleware pipeline |
| 102 | +- `config/routes.php`, with routing directives |
| 103 | +- `config/autoload/zend-expressive.global.php`, with settings to ensure |
| 104 | + programmatic pipelines are used, and new middleware provided for Expressive |
| 105 | + 2.0 is registered. |
| 106 | +- directives within `public/index.php` for using the generated pipeline and |
| 107 | + routes directives. |
| 108 | +
|
| 109 | +To use this feature, you will need to first install |
| 110 | +zendframework/zend-expressive-tooling: |
| 111 | +
|
| 112 | +```bash |
| 113 | +$ composer require --dev zendframework/zend-expressive-tooling |
| 114 | +``` |
| 115 | +
|
| 116 | +Invoke it as follows: |
| 117 | +
|
| 118 | +```bash |
| 119 | +$ ./vendor/bin/expressive-pipeline-from-config generate |
| 120 | +``` |
| 121 | +
|
| 122 | +The tool will notify you of any errors, including whether or not it found (and |
| 123 | +skipped) Stratigility v1-style "error middleware". |
| 124 | +
|
| 125 | +## Detect usage of legacy getOriginal*() calls |
| 126 | +
|
| 127 | +- Since 2.0. |
| 128 | +
|
| 129 | +When upgrading to version 2.0, you will also receive an upgrade to |
| 130 | +zendframework/zend-stratigility 2.0. That version eliminates internal decorator |
| 131 | +classes for the request and response instances, which were used to provide |
| 132 | +access to the outermost request/response; internal layers could use these to |
| 133 | +determine the full URI that resulted in their invocation, which is useful when |
| 134 | +you pipe using a path argument (as the path provided during piping is stripped |
| 135 | +from the URI when invoking the matched middleware). |
| 136 | +
|
| 137 | +This affects the following methods: |
| 138 | +
|
| 139 | +- `Request::getOriginalRequest()` |
| 140 | +- `Request::getOriginalUri()` |
| 141 | +- `Response::getOriginalResponse()` |
| 142 | +
|
| 143 | +To provide equivalent functionality, we provide a couple of tools. |
| 144 | +
|
| 145 | +First, Stratigility provides middleware, `Zend\Stratigility\Middleware\OriginalMessages`, |
| 146 | +which will inject the current request, its URI, and, if invoked as double-pass |
| 147 | +middleware, current response, as _request attributes_, named, respectively, |
| 148 | +`originalRequest`, `originalUri`, and `originalResponse`. (Since Expressive 2.0 |
| 149 | +decorates double-pass middleware using a wrapper that composes a response, the |
| 150 | +"original response" will be the response prototype composed in the `Application` |
| 151 | +instance.) This should be registered as the outermost middleware layer. |
| 152 | +Middleware that needs access to these instances can then use the following |
| 153 | +syntax to retrieve them: |
| 154 | +
|
| 155 | +```php |
| 156 | +$originalRequest = $request->getAttribute('originalRequest', $request); |
| 157 | +$originalUri = $request->getAttribute('originalUri', $request->getUri(); |
| 158 | +$originalResponse = $request->getAttribute('originalResponse') ?: new Response(); |
| 159 | +``` |
| 160 | +
|
| 161 | +> ### Original response is not trustworthy |
| 162 | +> |
| 163 | +> As noted above, the "original response" will likely be injected with the |
| 164 | +> response prototype from the `Application` instance. We recommend not using it, |
| 165 | +> and instead either composing a pristine response instance in your middleware, |
| 166 | +> or creating a new instance on-the-fly. |
| 167 | +
|
| 168 | +To aid you in migrating your existing code to use the new `getAttribute()` |
| 169 | +syntax, zendframework/zend-expressive-tooling provides a binary, |
| 170 | +`vendor/bin/expressive-migrate-original-messages`. First, install that package: |
| 171 | +
|
| 172 | +```bash |
| 173 | +$ composer require --dev zendframework/zend-expressive-tooling |
| 174 | +``` |
| 175 | +
|
| 176 | +Then invoke it as follows: |
| 177 | +
|
| 178 | +```bash |
| 179 | +$ ./vendor/bin/expressive-migrate-original-messages scan |
| 180 | +``` |
| 181 | +
|
| 182 | +This script will update any `getOriginalRequest()` and `getOriginalUri()` calls, |
| 183 | +and notify you of any `getOriginalResponse()` calls, providing you with details |
| 184 | +on how to correct those manually. |
| 185 | +
|
| 186 | +## Detect usage of legacy error middleware |
| 187 | +
|
| 188 | +- Since 2.0. |
| 189 | +
|
| 190 | +When upgrading to version 2.0, you will also receive an upgrade to |
| 191 | +zendframework/zend-stratigility 2.0. That version eliminates what was known as |
| 192 | +"error middleware", middleware that either implemented |
| 193 | +`Zend\Stratigility\ErrorMiddlewareInterface`, or duck-typed it by implementing |
| 194 | +the signature `function ($error, $request, $response, callable $next)`. |
| 195 | +
|
| 196 | +Such "error middleware" allowed other middleware to invoke the `$next` argument |
| 197 | +with an additional, third argument representing an error condition; when that |
| 198 | +occurred, Stratigility/Expressive would start iterating through error middleware |
| 199 | +until one was able to return a response. Each would receive the error as the |
| 200 | +first argument, and determine how to act upon it. |
| 201 | +
|
| 202 | +With version 2.0 of each project, such middleware is now no longer accepted, and |
| 203 | +users should instead be using [the new error handling |
| 204 | +features](../features/error-handling.md). However, you may find that: |
| 205 | +
|
| 206 | +- You have defined error middleware in your application. |
| 207 | +- You have standard middleware in your application that invokes `$next` with the |
| 208 | + third, error argument. |
| 209 | +
|
| 210 | +To help you identify such instances, zendframework/zend-expressive-tooling |
| 211 | +provides the script `vendor/bin/expressive-scan-for-error-middleware`. First, |
| 212 | +install that package: |
| 213 | +
|
| 214 | +```bash |
| 215 | +$ composer require --dev zendframework/zend-expressive-tooling |
| 216 | +``` |
| 217 | +
|
| 218 | +Then invoke it as follows: |
| 219 | +
|
| 220 | +```bash |
| 221 | +$ ./vendor/bin/expressive-scan-for-error-middleware scan |
| 222 | +``` |
| 223 | +
|
| 224 | +The script will notify you of any places where it finds either use case, and |
| 225 | +provide feedback on how to update your application. |
0 commit comments