The Zend Framework community is pleased to announce the immediate availability of Expressive 1.0.0rc7 and the Expressive Skeleton and Installer 1.0.0rc8!

You can install the latest versions using Composer, via the create-project command:

$ composer create-project -s rc zendframework/zend-expressive-skeleton expressive

You can update your existing applications using:

$ composer update

This release candidate contains bug fixes for dispatching error middleware pipelines. Additionally, we've released a new version of our Twig integration, and detail those changes below.

Changes in zend-expressive RC7

RC6 updated the configuration for the middleware pipeline to make it a single pipeline. We recommended that developers make use of our middleware grouping feature, however, which allows you to specify not just a single, named middleware service, but an array of named middleware services. This feature is great for grouping middleware based on when it should execute, and makes ordering related middleware simpler.

Per our suggested, default configuration:

use Zend\Expressive\Container\ApplicationFactory;
use Zend\Expressive\Helper;

return [
    'dependencies' => [
        'factories' => [
            Helper\ServerUrlMiddleware::class => Helper\ServerUrlMiddlewareFactory::class,
            Helper\UrlHelperMiddleware::class => Helper\UrlHelperMiddlewareFactory::class,
        ],
    ],
    // This can be used to seed pre- and/or post-routing middleware
    'middleware_pipeline' => [
        // An array of middleware to register. Each item is of the following
        // specification:
        //
        // [
        //  Required:
        //     'middleware' => 'Name or array of names of middleware services and/or callables',
        //  Optional:
        //     'path'     => '/path/to/match', // string; literal path prefix to match
        //                                     // middleware will not execute
        //                                     // if path does not match!
        //     'error'    => true, // boolean; true for error middleware
        //     'priority' => 1, // int; higher values == register early;
        //                      // lower/negative == register last;
        //                      // default is 1, if none is provided.
        // ],
        //
        // While the ApplicationFactory ignores the keys associated with
        // specifications, they can be used to allow merging related values
        // defined in multiple configuration files/locations. This file defines
        // some conventional keys for middleware to execute early, routing
        // middleware, and error middleware.
        'always' => [
            'middleware' => [
                // Add more middleware here that you want to execute on
                // every request:
                // - bootstrapping
                // - pre-conditions
                // - modifications to outgoing responses
                Helper\ServerUrlMiddleware::class,
            ],
            'priority' => 10000,
        ],

        'routing' => [
            'middleware' => [
                ApplicationFactory::ROUTING_MIDDLEWARE,
                Helper\UrlHelperMiddleware::class,
                // Add more middleware here that needs to introspect the routing
                // results; this might include:
                // - route-based authentication
                // - route-based validation
                // - etc.
                ApplicationFactory::DISPATCH_MIDDLEWARE,
            ],
            'priority' => 1,
        ],

        'error' => [
            'middleware' => [
                // Add error middleware here.
            ],
            'priority' => -10000,
            'error' => true,
        ],
    ],
];

Unfortunately, for error middleware, this was not working correctly.

Internally, when we encounter an array of middleware, we create a Zend\Stratigility\MiddlewarePipe instance, and pipe each middleware service to it in order. The problem is that MiddlewarePipe does not implement the error middleware signature — which meant that error middleware pipelines were completely skipped!

To make this work, we introduced a proxy class, Zend\Expressive\ErrorMiddlewarePipe, which wraps a MiddlewarePipe, and exposes the error middleware signature. This is now used internally whenever an error middleware pipeline needs to be created.

Changes in zend-expressive-skeleton RC8

When we created the new default middleware pipeline configuration for RC6/RC7, we forgot one important detail: the error middleware group was missing its error key, meaning it wasn't attempting to create error middleware at all! We've fixed this in RC8.

If you upgraded to RC6/RC7 earlier this week, make sure you add that error key, as detailed in the above example.

Twig integration updates

Today we released version 1.0.1 of our Twig integration. This includes a few new features:

  • It adds a dependency on zend-expressive-helpers and, if the UrlHelper and ServerUrlHelper services are registered, makes new url and absolute_url template functions available.
  • It adds a new "globals" configuration sub-section for registering variables to pass to all templates.

You can read more in the Twig integration documentation.

Many thanks to Geert Eltink for these new features!

Future

Code is stabilizing, and we're seeing fewer issues hitting our issue tracker. We hope that in a week or two we can release a stable version.

If you are testing Expressive — whether for the first time, or updating an existing application — please help us prepare it for general availability!

Source

The Zend Framework community is pleased to announce the immediate availability of Expressive 1.0.0rc6 and 1.0.0rc7!

You can install the latest versions using Composer, via the create-project command:

$ composer create-project -s rc zendframework/zend-expressive-skeleton expressive

You can update your existing applications using:

$ composer update

Unfortunately, zend-expressive RC6 introduces some breaking changes. Several issues were raised that could not be handled in a fully backwards compatible fashion, and we felt they were important enough to introduce before a stable release is made. We continue to honor previous application configuration; however, deprecation notices will be raised, and the code for parsing the old configuration will be removed for the 1.1 release.

We also released zend-expressive-skeleton RC7 quick on the heels of RC6 in order to correct an issue with installation whereby the development dependencies at time of invocation were installed, rather than the rewritten ones. This affected only the skeleton, which is why we're announcing RC6 and RC7 releases.

See below for full details on what has changed.

Changes in zend-expressive RC6

Like RC5, the bulk of the changes merged for RC6 were documentation, including:

Unlike RC5, however, we introduced a significant code change, prompted by user feedback. In particular, we saw each of the following reported multiple times:

  • confusion over the pre_routing and post_routing middleware pipeline keys, and how they relate to routed middleware.
  • requests to split the routing middleware into two distinct responsibilities: routing middleware, and dispatch middleware.
  • requests to allow dispatching middleware when triggering route result observers.

On analysis, and in discussions with users, we decided to make the following changes.

Splitting the routing middleware

We split the routing middleware into two discrete methods: routing and dispatch. This solved multiple problems, and enables a number of interesting workflows.

In particular, it allows you to define middleware that can act on the routing results in order to satisify pre-conditions in an automated way.

As an example, let's say you have a workflow where you want to:

  • Authenticate a user
  • Authorize the user
  • Perform content negotiation
  • Validate incoming body parameters

However, you don't want to perform these actions for every request, only specific routes.

Previously, you would need to define an array of middleware for each route that needs this set of responsibilities:

[
    'routes' => [
        'api.ping' => [
            'path' => '/api/ping',
            'middleware' => [
                AuthenticationMiddleware::class,
                AuthorizationMiddleware::class,
                ContentNegotiationMiddleware::class,
                BodyValidationMiddleware::class,
                PingMiddleware::class,
            ],
            'allowed_methods' => ['GET'],
        ],
        'api.books' => [
            'path' => '/api/books[/{id:[a-f0-9]{8}}]',
            'middleware' => [
                AuthenticationMiddleware::class,
                AuthorizationMiddleware::class,
                ContentNegotiationMiddleware::class,
                BodyValidationMiddleware::class,
                BooksMiddleware::class,
            ],
        ],
        /* etc. */
    ],
]

This is repetitive, and prone to error: any change in the workflow requires propagation to every route.

Splitting the routing and dispatch middleware allows you to pipe middleware between the two actions, allowing you to register such workflows once. The middleware could then introspect the route results to determine if they have work to do.

This means you can now write middleware like this:

use Zend\Expressive\Router\RouteResult;

$authenticationMiddleware = function ($request, $response, $next) use ($map, $authenticate) {
    $routeResult = $request->getAttribute(RouteResult::class, false);
    if (! $routeResult instanceof RouteResult) {
        return $next($request, $response);
    }

    if (! in_array($routeResult->getMatchedRouteName(), $map)) {
        return $next($request, $response);
    }

    $authenticationResult = $authenticate($request);
    if (! $authenticationResult->isSuccess()) {
        // ERROR!
        return new AuthenticationErrorResponse();
    }

    return $next(
        $request->withAttribute($authenticationResult->getIdentity()),
        $response
    );
}

You would then sandwich it between the routing and dispatch middleware. Programmatically, that looks like:

$app->pipeRoutingMiddleware();
$app->pipe($authenticationMiddleware);
$app->pipeDispatchMiddleware();

We'll look at configuration later, as it changes more dramatically.

No more auto-registration of the routing middleware

Prior to RC6, the routing middleware was auto-registered when:

  • any call to route() was made, including those via the methods that proxy to it (get(), post(), any(), etc.).
  • as soon as the Application instance was invoked as middleware (i.e., by calling $app($request, $response) or calling $app->run()).

You could also always register it manually when creating your application pipeline using the pipeRoutingMiddleware() method.

Because routing was split into two distinct actions, and one primary purpose for doing so was to allow registering middleware between those actions, we felt that auto-registration was not only no longer useful, but a liability.

As such, when creating your application programmatically, there is now exactly one workflow to use to enable the routing and dispatch middleware: each must be piped explicitly into the pipeline:

$app->pipe(ServerUrlMiddleware::class);
$app->pipe(BaseParamsMiddleware::class);
$app->pipeRoutingMiddleware();
$app->pipe(UrlHelperMiddleware::class);
$app->pipeDispatchMiddleware();

If you are building your application programmatically, you must update it to pipe the routing and dispatch middleware in order for it to continue to work.

We'll look at configuration for the ApplicationFactory later, as it changes as well.

No more route result observers

Another consequence of splitting the routing middleware in two was a pleasant discovery: there was no longer any need for the route result observer system!

The route result observer system was added in RC3 to allow the application to notify interested observers of the results of routing, as there was no other way to trigger functionality between the act of routing and when the matched middleware was dispatched (if any was actually matched!).

Several developers complained that they couldn't return a response from these observers when they detected an error condition, nor could they introspect the request in such situations.

With the routing middleware split, there's an answer to those questions, and the observer system is no longer needed; just place middleware between the routing and dispatch middleware, and have it act on the RouteResult instance (which the routing middleware injects as a request attribute). In fact, we've already demonstrated this above!

For RC6, we removed the RouteResultSubjectInterface implementation from the Application instance, while keeping the original methods defined in that interface; these methods now trigger deprecation notices. If you were using observers previously, and keep your existing RC5 configuration, we also inject a special "route result observer middleware" between the routing and dispatch middleware that will notify the observers. The deprecation messages will prompt you to update your code, and provide a link to the migration guide to help you.

A new minor version of zend-expressive-router was released, v1.2.0, marking each of the RouteResultSubjectInterface and RouteResultObserverInterface as deprecated.

A new major version of zend-expressive-helpers was released, v2.0.0, that removes the RouteResultObserverInterface implementation from the UrlHelper, and updates its related middleware to act between the routing and dispatch middleware.

Simplified configuration

We've alluded to configuration changes several times; it's now time to detail those.

One common confusion that arose was around the pre_routing and post_routing names. Many assumed that pre_routing meant that the middleware listed only operated before routing — and did not realize that such middleware could also post-process responses. Similarly, many assumed that post_routing middleware was executed after routed middleware, even when the routed middleware returned a response (it was only executed if the routed middleware called $next() or if an error occurred).

We wanted to clarify how the middleware pipeline worked, and with the switch to split the routing and dispatch middleware, and a desire to allow injecting middleware between routing and dispatch, we had an opportunity to positiveily change the configuration to make it more clear.

Enrico suggested that instead of segregating into pre/post, we have a single pipeline. This would require defining entries for the routing and dispatch middleware as part of the pipeline, but you would then be able to see the exact workflow.

One counter-argument, however, is when merging configuration, which is done by default in the skeleton, and which is a recommended practice to keep configuration for related functionality in discrete places. How would order be preserved?

We decided to introduce a priority key into our middleware configuration specifications. This works with SplPriorityQueue: higher values are piped earlier and execute earlier, while lower/negative values are piped later. This provides the ability to define the pipeline across multiple files, merge it, and get a predictable order.

Additionally, we realized we could lever another existing feature: middleware specifications used by the pipeline configuration allow you to specify lists of middleware to execute, not just individual middleware. This means that you can group middleware under the same priority, in the order you want it to execute. This is a great technique for segregating configuration.

What we came up with ends up looking like this when you start out with the new skeleton:

use Zend\Expressive\Container\ApplicationFactory;
use Zend\Expressive\Helper;

return [
    'dependencies' => [
        'factories' => [
            Helper\ServerUrlMiddleware::class => Helper\ServerUrlMiddlewareFactory::class,
            Helper\UrlHelperMiddleware::class => Helper\UrlHelperMiddlewareFactory::class,
        ],
    ],
    // This can be used to seed pre- and/or post-routing middleware
    'middleware_pipeline' => [
        // An array of middleware to register. Each item is of the following
        // specification:
        //
        // [
        //  Required:
        //     'middleware' => 'Name or array of names of middleware services and/or callables',
        //  Optional:
        //     'path'     => '/path/to/match', // string; literal path prefix to match
        //                                     // middleware will not execute
        //                                     // if path does not match!
        //     'error'    => true, // boolean; true for error middleware
        //     'priority' => 1, // int; higher values == register early;
        //                      // lower/negative == register last;
        //                      // default is 1, if none is provided.
        // ],
        //
        // While the ApplicationFactory ignores the keys associated with
        // specifications, they can be used to allow merging related values
        // defined in multiple configuration files/locations. This file defines
        // some conventional keys for middleware to execute early, routing
        // middleware, and error middleware.
        'always' => [
            'middleware' => [
                // Add more middleware here that you want to execute on
                // every request:
                // - bootstrapping
                // - pre-conditions
                // - modifications to outgoing responses
                Helper\ServerUrlMiddleware::class,
            ],
            'priority' => 10000,
        ],

        'routing' => [
            'middleware' => [
                ApplicationFactory::ROUTING_MIDDLEWARE,
                Helper\UrlHelperMiddleware::class,
                // Add more middleware here that needs to introspect the routing
                // results; this might include:
                // - route-based authentication
                // - route-based validation
                // - etc.
                ApplicationFactory::DISPATCH_MIDDLEWARE,
            ],
            'priority' => 1,
        ],

        'error' => [
            'middleware' => [
                // Add error middleware here.
            ],
            'priority' => -10000,
        ],
    ],
];

For existing users:

  • Existing RC5 and earlier configuration is still honored, but will emit deprecation notices, prompting you to update; these notices include links to the migration guide.
  • To update, you'll need to:
    • update your zend-expressive-helpers version constraint to ^2.0.
    • update your configuration, using the above as a guide.

We're excited about this change, as we feel it simplifies the configuration, adds flexibility, and provides predictability in the system. While it is a large change for a release candidate, we also felt it was important enough to warrant introducing before the stable release.

Full migration details

The above narrative is use-case-centered. We have, however, published a full migration guide as part of the release to give exact details on changes you will need to make.

Future

At this point, we feel that the code has stabilized significantly, and that the improvements in these latest releases have provided important simplicity and flexibility to make the system robust. We'll be waiting a week or two to see how you, our users, respond, and hopefully be able to tag a stable release shortly!

If you are testing Expressive — whether for the first time, or updating an existing application — please help us prepare it for general availability!

Source

The Zend Framework community is pleased to announce the immediate availability of Expressive 1.0.0rc6 and 1.0.0rc7!

You can install the latest versions using Composer, via the create-project command:

$ composer create-project -s rc zendframework/zend-expressive-skeleton expressive

You can update your existing applications using:

$ composer update

Unfortunately, zend-expressive RC6 introduces some breaking changes. Several issues were raised that could not be handled in a fully backwards compatible fashion, and we felt they were important enough to introduce before a stable release is made. We continue to honor previous application configuration; however, deprecation notices will be raised, and the code for parsing the old configuration will be removed for the 1.1 release.

We also released zend-expressive-skeleton RC7 quick on the heels of RC6 in order to correct an issue with installation whereby the development dependencies at time of invocation were installed, rather than the rewritten ones. This affected only the skeleton, which is why we're announcing RC6 and RC7 releases.

See below for full details on what has changed.

Changes in zend-expressive RC6

Like RC5, the bulk of the changes merged for RC6 were documentation, including:

Unlike RC5, however, we introduced a significant code change, prompted by user feedback. In particular, we saw each of the following reported multiple times:

  • confusion over the pre_routing and post_routing middleware pipeline keys, and how they relate to routed middleware.
  • requests to split the routing middleware into two distinct responsibilities: routing middleware, and dispatch middleware.
  • requests to allow dispatching middleware when triggering route result observers.

On analysis, and in discussions with users, we decided to make the following changes.

Splitting the routing middleware

We split the routing middleware into two discrete methods: routing and dispatch. This solved multiple problems, and enables a number of interesting workflows.

In particular, it allows you to define middleware that can act on the routing results in order to satisify pre-conditions in an automated way.

As an example, let's say you have a workflow where you want to:

  • Authenticate a user
  • Authorize the user
  • Perform content negotiation
  • Validate incoming body parameters

However, you don't want to perform these actions for every request, only specific routes.

Previously, you would need to define an array of middleware for each route that needs this set of responsibilities:

[
    'routes' => [
        'api.ping' => [
            'path' => '/api/ping',
            'middleware' => [
                AuthenticationMiddleware::class,
                AuthorizationMiddleware::class,
                ContentNegotiationMiddleware::class,
                BodyValidationMiddleware::class,
                PingMiddleware::class,
            ],
            'allowed_methods' => ['GET'],
        ],
        'api.books' => [
            'path' => '/api/books[/{id:[a-f0-9]{8}}]',
            'middleware' => [
                AuthenticationMiddleware::class,
                AuthorizationMiddleware::class,
                ContentNegotiationMiddleware::class,
                BodyValidationMiddleware::class,
                BooksMiddleware::class,
            ],
        ],
        /* etc. */
    ],
]

This is repetitive, and prone to error: any change in the workflow requires propagation to every route.

Splitting the routing and dispatch middleware allows you to pipe middleware between the two actions, allowing you to register such workflows once. The middleware could then introspect the route results to determine if they have work to do.

This means you can now write middleware like this:

use Zend\Expressive\Router\RouteResult;

$authenticationMiddleware = function ($request, $response, $next) use ($map, $authenticate) {
    $routeResult = $request->getAttribute(RouteResult::class, false);
    if (! $routeResult instanceof RouteResult) {
        return $next($request, $response);
    }

    if (! in_array($routeResult->getMatchedRouteName(), $map)) {
        return $next($request, $response);
    }

    $authenticationResult = $authenticate($request);
    if (! $authenticationResult->isSuccess()) {
        // ERROR!
        return new AuthenticationErrorResponse();
    }

    return $next(
        $request->withAttribute($authenticationResult->getIdentity()),
        $response
    );
}

You would then sandwich it between the routing and dispatch middleware. Programmatically, that looks like:

$app->pipeRoutingMiddleware();
$app->pipe($authenticationMiddleware);
$app->pipeDispatchMiddleware();

We'll look at configuration later, as it changes more dramatically.

No more auto-registration of the routing middleware

Prior to RC6, the routing middleware was auto-registered when:

  • any call to route() was made, including those via the methods that proxy to it (get(), post(), any(), etc.).
  • as soon as the Application instance was invoked as middleware (i.e., by calling $app($request, $response) or calling $app->run()).

You could also always register it manually when creating your application pipeline using the pipeRoutingMiddleware() method.

Because routing was split into two distinct actions, and one primary purpose for doing so was to allow registering middleware between those actions, we felt that auto-registration was not only no longer useful, but a liability.

As such, when creating your application programmatically, there is now exactly one workflow to use to enable the routing and dispatch middleware: each must be piped explicitly into the pipeline:

$app->pipe(ServerUrlMiddleware::class);
$app->pipe(BaseParamsMiddleware::class);
$app->pipeRoutingMiddleware();
$app->pipe(UrlHelperMiddleware::class);
$app->pipeDispatchMiddleware();

If you are building your application programmatically, you must update it to pipe the routing and dispatch middleware in order for it to continue to work.

We'll look at configuration for the ApplicationFactory later, as it changes as well.

No more route result observers

Another consequence of splitting the routing middleware in two was a pleasant discovery: there was no longer any need for the route result observer system!

The route result observer system was added in RC3 to allow the application to notify interested observers of the results of routing, as there was no other way to trigger functionality between the act of routing and when the matched middleware was dispatched (if any was actually matched!).

Several developers complained that they couldn't return a response from these observers when they detected an error condition, nor could they introspect the request in such situations.

With the routing middleware split, there's an answer to those questions, and the observer system is no longer needed; just place middleware between the routing and dispatch middleware, and have it act on the RouteResult instance (which the routing middleware injects as a request attribute). In fact, we've already demonstrated this above!

For RC6, we removed the RouteResultSubjectInterface implementation from the Application instance, while keeping the original methods defined in that interface; these methods now trigger deprecation notices. If you were using observers previously, and keep your existing RC5 configuration, we also inject a special "route result observer middleware" between the routing and dispatch middleware that will notify the observers. The deprecation messages will prompt you to update your code, and provide a link to the migration guide to help you.

A new minor version of zend-expressive-router was released, v1.2.0, marking each of the RouteResultSubjectInterface and RouteResultObserverInterface as deprecated.

A new major version of zend-expressive-helpers was released, v2.0.0, that removes the RouteResultObserverInterface implementation from the UrlHelper, and updates its related middleware to act between the routing and dispatch middleware.

Simplified configuration

We've alluded to configuration changes several times; it's now time to detail those.

One common confusion that arose was around the pre_routing and post_routing names. Many assumed that pre_routing meant that the middleware listed only operated before routing — and did not realize that such middleware could also post-process responses. Similarly, many assumed that post_routing middleware was executed after routed middleware, even when the routed middleware returned a response (it was only executed if the routed middleware called $next() or if an error occurred).

We wanted to clarify how the middleware pipeline worked, and with the switch to split the routing and dispatch middleware, and a desire to allow injecting middleware between routing and dispatch, we had an opportunity to positiveily change the configuration to make it more clear.

Enrico suggested that instead of segregating into pre/post, we have a single pipeline. This would require defining entries for the routing and dispatch middleware as part of the pipeline, but you would then be able to see the exact workflow.

One counter-argument, however, is when merging configuration, which is done by default in the skeleton, and which is a recommended practice to keep configuration for related functionality in discrete places. How would order be preserved?

We decided to introduce a priority key into our middleware configuration specifications. This works with SplPriorityQueue: higher values are piped earlier and execute earlier, while lower/negative values are piped later. This provides the ability to define the pipeline across multiple files, merge it, and get a predictable order.

Additionally, we realized we could lever another existing feature: middleware specifications used by the pipeline configuration allow you to specify lists of middleware to execute, not just individual middleware. This means that you can group middleware under the same priority, in the order you want it to execute. This is a great technique for segregating configuration.

What we came up with ends up looking like this when you start out with the new skeleton:

use Zend\Expressive\Container\ApplicationFactory;
use Zend\Expressive\Helper;

return [
    'dependencies' => [
        'factories' => [
            Helper\ServerUrlMiddleware::class => Helper\ServerUrlMiddlewareFactory::class,
            Helper\UrlHelperMiddleware::class => Helper\UrlHelperMiddlewareFactory::class,
        ],
    ],
    // This can be used to seed pre- and/or post-routing middleware
    'middleware_pipeline' => [
        // An array of middleware to register. Each item is of the following
        // specification:
        //
        // [
        //  Required:
        //     'middleware' => 'Name or array of names of middleware services and/or callables',
        //  Optional:
        //     'path'     => '/path/to/match', // string; literal path prefix to match
        //                                     // middleware will not execute
        //                                     // if path does not match!
        //     'error'    => true, // boolean; true for error middleware
        //     'priority' => 1, // int; higher values == register early;
        //                      // lower/negative == register last;
        //                      // default is 1, if none is provided.
        // ],
        //
        // While the ApplicationFactory ignores the keys associated with
        // specifications, they can be used to allow merging related values
        // defined in multiple configuration files/locations. This file defines
        // some conventional keys for middleware to execute early, routing
        // middleware, and error middleware.
        'always' => [
            'middleware' => [
                // Add more middleware here that you want to execute on
                // every request:
                // - bootstrapping
                // - pre-conditions
                // - modifications to outgoing responses
                Helper\ServerUrlMiddleware::class,
            ],
            'priority' => 10000,
        ],

        'routing' => [
            'middleware' => [
                ApplicationFactory::ROUTING_MIDDLEWARE,
                Helper\UrlHelperMiddleware::class,
                // Add more middleware here that needs to introspect the routing
                // results; this might include:
                // - route-based authentication
                // - route-based validation
                // - etc.
                ApplicationFactory::DISPATCH_MIDDLEWARE,
            ],
            'priority' => 1,
        ],

        'error' => [
            'middleware' => [
                // Add error middleware here.
            ],
            'priority' => -10000,
        ],
    ],
];

For existing users:

  • Existing RC5 and earlier configuration is still honored, but will emit deprecation notices, prompting you to update; these notices include links to the migration guide.
  • To update, you'll need to:
    • update your zend-expressive-helpers version constraint to ^2.0.
    • update your configuration, using the above as a guide.

We're excited about this change, as we feel it simplifies the configuration, adds flexibility, and provides predictability in the system. While it is a large change for a release candidate, we also felt it was important enough to warrant introducing before the stable release.

Full migration details

The above narrative is use-case-centered. We have, however, published a full migration guide as part of the release to give exact details on changes you will need to make.

Future

At this point, we feel that the code has stabilized significantly, and that the improvements in these latest releases have provided important simplicity and flexibility to make the system robust. We'll be waiting a week or two to see how you, our users, respond, and hopefully be able to tag a stable release shortly!

If you are testing Expressive — whether for the first time, or updating an existing application — please help us prepare it for general availability!

Source

This is an installment in an ongoing series of bi-weekly posts on ZF3 development status.

Following a roughly two week hiatus at the end of the year, we've picked up where we left off and continued the momentum towards the ZF3 initiatives.

The highlights:

  • 48 pull requests merged
  • 11 releases of components, including 3 3.0 releases in 3 days!
  • 6 components updated to zend-servicemanager/zend-eventmanager v3 changes
  • Major updates for an upcoming Expressive RC6

3.0 Releases!

A number of components reached stability in the past few weeks, and this week we did a spree of three 3.0 releases in three days:

  • zend-servicemanager 3.0.0 is the first 3.0 release of any ZF components, and features a complete rewrite of the internals to provide up to 4x faster performance! We have been careful to retain as much backwards compatibility as possible, and the v2.7.0 release provides features that make migration between versions seamless for users. A migration guide is available.
  • zend-eventmanager 3.0.0 is our second 3.0 release of a ZF component, and features a complete rewrite of the internals of the EventManager implementation to provide up to 4X faster performance. By following the migration guide, you can update your v2 code to work on both v2 and v3.
  • zend-code 3.0.0 is our third 3.0 release of a ZF component, and features updates to allow usage with PHP 5.5, 5.6, and PHP 7, and, specifically, scalar typehints, return typehints, generators, and variadics.

Be aware that you cannot make use of these new 3.0 versions within existing ZF2 applications quite yet; we are still in the process of updating components to work with these releases. However, they can be used standalone, or within projects based on Expressive!

Pull request activity

Since the last update, we've merged 48 pull requests (link requires a GitHub account). Activity has been particularly high on Expressive, zend-servicemanager, and components refactoring to the latest zend-servicemanager and zend-eventmanager updates.

Component Releases

The following is a list of component releases (other than the 3.0 releases listed above) since the last update. While not all releases are related to ZF3 specifically, this list is intended to detail activity within the organization.

  • zend-expressive-helpers 1.4.0 adds base path support to the UrlHelper.
  • Diactoros 1.3.3 fixes an issue in ServerRequestFactory::marshalHeaders() whereby we were explicitly omitting cookie headers; they are now aggregated.
  • zend-expressive-zendrouter 1.0.1 fixes an issue whereby appending a trailing slash when requesting a route that did not define one resulted in a 405 instead of a 404 error.
  • zend-servicemanager 2.7.0, zend-servicemanager 2.7.1, zend-servicemanager 2.7.2, and zend-servicemanager 2.7.3 are forwards-compatibility releases, providing several features that allow users to update their code to work with both the v2 and v3 series of the service manager.
  • zend-eventmanager 2.6.2 introduces a trait, EventListenerIntrospectionTrait, for use with PHPUnit test cases. It provides a consistent API for introspecting what events and listeners are attached to an EventManager instance, and provides a custom assertion for validating that a given listener is registered at a given priority on a given event. This trait can be used to write assertions for validating listener attachment in a way that will be forwards compatible with version 3.

ZF3 Refactors

Since the last update, the following components have been refactored to work with the planned v3 versions of zend-servicemanager and zend-eventmanager. Please note that no new versions have been released at this time; all work remains either in pull requests or in the develop branches of each component.

Additionally, we have created pull requests for several components to work with the forwards compatibility releases of zend-servicemanager and zend-eventmanager. These will allow us to release 2.x versions of these components that can be used by code consuming the v3 versions of those two components.

Expressive

We've had quite a number of people testing Expressive heavily, and pointing out both its strengths and weaknesses. This has resulted in a ton of additional tests, bringing coverage to 100% in some cases, as well as copious amounts of new documentation.

After several issue threads and IRC conversations, we've decided to release an additional RC, RC6, to accomplish the following:

  • Simplification of the middleware pipeline; we will be doing away with the pre_routing and post_routing keys, and allowing a single pipeline representing the entire application lifecycle.
  • Splitting of the routing middleware into separate routing and dispatch middleware. This allows developers to tie into the application lifecycle using middleware between routing and dispatch, facilitating such things as route-based authentication, validation, etc.
  • Removal of auto-registration of the routing middleware; this is done to allow substituting alternative routing middleware and/or dispatch middleware.
  • Deprecation of the route result observer system. The same functionality can now be accomplished with middleware that acts between routing and dispatch.

We've attempted to preserve backwards compatibility for existing applications, but have marked deprecated features for removal with 1.1. A migration guide will assist our early adopters in updating their applications.

Until next time

If you want to help:

Many thanks to all the contributors who have provided feedback, patches, reviews, or releases! In particular, I want to call out:

  • Marco Pivetta for his work on updating zend-code to work with PHP 7 (and PHP 5.5, and PHP 5.6) features.
  • Michaël Gallego for his work on the zend-servicemanager and zend-eventmanager refactors, and his relentless pursuit of performance increases.
  • Enrico Zimuel for his work on the zend-eventmanager refactor, and taking on the drudgery of updating components to the new zend-eventmanager and zend-servicemanager changes.
  • Ralf Eggert and Daniel Gimenes for the constant stream of questions and suggestions for Expressive; their feedback is changing it for the better!

Source

This is an installment in an ongoing series of bi-weekly posts on ZF3 development status.

Following a roughly two week hiatus at the end of the year, we've picked up where we left off and continued the momentum towards the ZF3 initiatives.

The highlights:

  • 48 pull requests merged
  • 11 releases of components, including 3 3.0 releases in 3 days!
  • 6 components updated to zend-servicemanager/zend-eventmanager v3 changes
  • Major updates for an upcoming Expressive RC6

3.0 Releases!

A number of components reached stability in the past few weeks, and this week we did a spree of three 3.0 releases in three days:

  • zend-servicemanager 3.0.0 is the first 3.0 release of any ZF components, and features a complete rewrite of the internals to provide up to 4x faster performance! We have been careful to retain as much backwards compatibility as possible, and the v2.7.0 release provides features that make migration between versions seamless for users. A migration guide is available.
  • zend-eventmanager 3.0.0 is our second 3.0 release of a ZF component, and features a complete rewrite of the internals of the EventManager implementation to provide up to 4X faster performance. By following the migration guide, you can update your v2 code to work on both v2 and v3.
  • zend-code 3.0.0 is our third 3.0 release of a ZF component, and features updates to allow usage with PHP 5.5, 5.6, and PHP 7, and, specifically, scalar typehints, return typehints, generators, and variadics.

Be aware that you cannot make use of these new 3.0 versions within existing ZF2 applications quite yet; we are still in the process of updating components to work with these releases. However, they can be used standalone, or within projects based on Expressive!

Pull request activity

Since the last update, we've merged 48 pull requests (link requires a GitHub account). Activity has been particularly high on Expressive, zend-servicemanager, and components refactoring to the latest zend-servicemanager and zend-eventmanager updates.

Component Releases

The following is a list of component releases (other than the 3.0 releases listed above) since the last update. While not all releases are related to ZF3 specifically, this list is intended to detail activity within the organization.

  • zend-expressive-helpers 1.4.0 adds base path support to the UrlHelper.
  • Diactoros 1.3.3 fixes an issue in ServerRequestFactory::marshalHeaders() whereby we were explicitly omitting cookie headers; they are now aggregated.
  • zend-expressive-zendrouter 1.0.1 fixes an issue whereby appending a trailing slash when requesting a route that did not define one resulted in a 405 instead of a 404 error.
  • zend-servicemanager 2.7.0, zend-servicemanager 2.7.1, zend-servicemanager 2.7.2, and zend-servicemanager 2.7.3 are forwards-compatibility releases, providing several features that allow users to update their code to work with both the v2 and v3 series of the service manager.
  • zend-eventmanager 2.6.2 introduces a trait, EventListenerIntrospectionTrait, for use with PHPUnit test cases. It provides a consistent API for introspecting what events and listeners are attached to an EventManager instance, and provides a custom assertion for validating that a given listener is registered at a given priority on a given event. This trait can be used to write assertions for validating listener attachment in a way that will be forwards compatible with version 3.

ZF3 Refactors

Since the last update, the following components have been refactored to work with the planned v3 versions of zend-servicemanager and zend-eventmanager. Please note that no new versions have been released at this time; all work remains either in pull requests or in the develop branches of each component.

Additionally, we have created pull requests for several components to work with the forwards compatibility releases of zend-servicemanager and zend-eventmanager. These will allow us to release 2.x versions of these components that can be used by code consuming the v3 versions of those two components.

Expressive

We've had quite a number of people testing Expressive heavily, and pointing out both its strengths and weaknesses. This has resulted in a ton of additional tests, bringing coverage to 100% in some cases, as well as copious amounts of new documentation.

After several issue threads and IRC conversations, we've decided to release an additional RC, RC6, to accomplish the following:

  • Simplification of the middleware pipeline; we will be doing away with the pre_routing and post_routing keys, and allowing a single pipeline representing the entire application lifecycle.
  • Splitting of the routing middleware into separate routing and dispatch middleware. This allows developers to tie into the application lifecycle using middleware between routing and dispatch, facilitating such things as route-based authentication, validation, etc.
  • Removal of auto-registration of the routing middleware; this is done to allow substituting alternative routing middleware and/or dispatch middleware.
  • Deprecation of the route result observer system. The same functionality can now be accomplished with middleware that acts between routing and dispatch.

We've attempted to preserve backwards compatibility for existing applications, but have marked deprecated features for removal with 1.1. A migration guide will assist our early adopters in updating their applications.

Until next time

If you want to help:

Many thanks to all the contributors who have provided feedback, patches, reviews, or releases! In particular, I want to call out:

  • Marco Pivetta for his work on updating zend-code to work with PHP 7 (and PHP 5.5, and PHP 5.6) features.
  • Michaël Gallego for his work on the zend-servicemanager and zend-eventmanager refactors, and his relentless pursuit of performance increases.
  • Enrico Zimuel for his work on the zend-eventmanager refactor, and taking on the drudgery of updating components to the new zend-eventmanager and zend-servicemanager changes.
  • Ralf Eggert and Daniel Gimenes for the constant stream of questions and suggestions for Expressive; their feedback is changing it for the better!

Source

This is the second in an ongoing series of bi-weekly posts on ZF3 development status.

The highlights:

  • 45 pull requests merged
  • 14 releases of components
  • 5 components updated to zend-servicemanager/zend-eventmanager v3 changes
  • 1 release candidates of expressive

Pull request activity

Activity has continued to be quite high the past couple weeks, though slower than the previous update, with 45 pull requests merged (link requires a GitHub account). While Expressive still dominates the list, many of these were related to ZF3 refactors and ongoing component maintenance.

Component Releases

The following is a list of component releases since the last update. While not all releases are related to ZF3 specifically, this list is intended to detail activity within the organization. It omits the Expressive release candidates, as well as new components, which will be listed later in this post.

  • zend-expressive-fastroute 1.0.1 released 2015-12-14; fixes an issue with the returned RouteResult, ensuring it contains the name, not the path, of the route matched.
  • zend-diactoros 1.2.1 was a bugfix release that fixed:
    • issues with how withHeader() handled replacing existing headers that used a different casing strategy.
    • the $statusCode argument of the Response to never allow null values.
    • constructor header validation on all message types to:
      • allow numeric values (e.g., Content-Length)
      • raise an exception on invalid header names (non-empty strings or non-string values)
      • raise an exception on invalid individual header values (non strings/non-numerics)
  • zend-diactoros 1.3.0 was a feature release adding:
    • SapiEmitterTrait, which replaces a number of methods in the SapiEmitter to provide a re-useable base for emitters; SapiEmitter was updated to use the trait instead of to directly define the methods.
    • SapiStreamEmitter provides functionality for iteratively emitting stream-based responses, and includes support for Content-Range headers.
  • zend-diactoros 1.3.1 was a bugfix release that fixed:
    • an issue in the response serializer, whereby the discovered status code wasn't being cast to an integer.
    • an issue in the various concrete, text-based response types whereby they were not rewinding the message body stream after creation, causing later calls to getContents() to return an empty string (as it was starting from the end of the stream). These now rewind the stream during initialization.
  • zend-diactoros 1.3.2 fixes an issue in the ServerRequestFactory whereby we were omitting parsing for and injection of the HTTP protocol version.
  • zend-psr7bridge 0.2.1 adds support for injecting generated PSR-7 instances with the cookies present in the zend-http request instance.
  • zend-math 2.5.2 fixes base conversions for base36 and below.
  • zend-server 2.6.0 adds support for unwinding {@inheritdoc} annotations, and fixes a misleading exception in reflectFunction.
  • zf-development-mode 2.1.2 fixes the factory to pull and set the configuration caching rules under the correct configuration key.
  • zend-expressive-helpers 1.2.1 adds the protected method getRouteResult(), to allow extensions access to the route result instance.
  • zend-expressive-helpers 1.3.0 adds a new general-purpose BodyParamsMiddleware, for parsing the request body and returning a new instance populated with the parsed body parameters. The solution uses a strategy pattern, allowing developers to provide additional strategies per their application needs.

ZF3 Refactors

Since the last update, the following components have been refactored to work with the planned v3 versions of zend-servicemanager and zend-eventmanager. Please note that no new versions have been released at this time; all work remains either in pull requests or in the develop branches of each component.

Component Installer

One idea floated for helping the goal of reducing dependencies in both zend-mvc and the zf2 meta-repository is to have components also act as modules. This would allow them to provide configuration, factories, and event listeners to the MVC runtime in a completely opt-in fashion. The one problem with the approach, however, is automating registration with the application.

To this end, we created a component installer. This package provides composer post un/install scripts that look for metadata in the package; if the metadata is present, the script adds an entry to the application's module list. Components are added to the top of the list, and modules to the bottom.

The new package can be installed as a global composer utility, or downloaded as a self-updateable PHAR file. We will begin updating components to expose themselves to this tooling soon, and update the application skeleton with the scripts as generated by the package, to automate the facilities for greenfield projects.

Expressive Release Candidate

Today, we issued a new release candidate of Expressive, RC5. Be sure to read the announcement to find out what changes have been made! The bulk of the work has gone into expanding the documentation to cover common use case scenarios.

Until next time

The winter holidays are upon our team at this time, and we do not expect much progress in the coming two weeks. Look for updates in January!

Until then, if you want to help:

Many thanks to all the contributors who have provided feedback, patches, reviews, or releases!

Source

This is the second in an ongoing series of bi-weekly posts on ZF3 development status.

The highlights:

  • 45 pull requests merged
  • 14 releases of components
  • 5 components updated to zend-servicemanager/zend-eventmanager v3 changes
  • 1 release candidates of expressive

Pull request activity

Activity has continued to be quite high the past couple weeks, though slower than the previous update, with 45 pull requests merged (link requires a GitHub account). While Expressive still dominates the list, many of these were related to ZF3 refactors and ongoing component maintenance.

Component Releases

The following is a list of component releases since the last update. While not all releases are related to ZF3 specifically, this list is intended to detail activity within the organization. It omits the Expressive release candidates, as well as new components, which will be listed later in this post.

  • zend-expressive-fastroute 1.0.1 released 2015-12-14; fixes an issue with the returned RouteResult, ensuring it contains the name, not the path, of the route matched.
  • zend-diactoros 1.2.1 was a bugfix release that fixed:
    • issues with how withHeader() handled replacing existing headers that used a different casing strategy.
    • the $statusCode argument of the Response to never allow null values.
    • constructor header validation on all message types to:
      • allow numeric values (e.g., Content-Length)
      • raise an exception on invalid header names (non-empty strings or non-string values)
      • raise an exception on invalid individual header values (non strings/non-numerics)
  • zend-diactoros 1.3.0 was a feature release adding:
    • SapiEmitterTrait, which replaces a number of methods in the SapiEmitter to provide a re-useable base for emitters; SapiEmitter was updated to use the trait instead of to directly define the methods.
    • SapiStreamEmitter provides functionality for iteratively emitting stream-based responses, and includes support for Content-Range headers.
  • zend-diactoros 1.3.1 was a bugfix release that fixed:
    • an issue in the response serializer, whereby the discovered status code wasn't being cast to an integer.
    • an issue in the various concrete, text-based response types whereby they were not rewinding the message body stream after creation, causing later calls to getContents() to return an empty string (as it was starting from the end of the stream). These now rewind the stream during initialization.
  • zend-diactoros 1.3.2 fixes an issue in the ServerRequestFactory whereby we were omitting parsing for and injection of the HTTP protocol version.
  • zend-psr7bridge 0.2.1 adds support for injecting generated PSR-7 instances with the cookies present in the zend-http request instance.
  • zend-math 2.5.2 fixes base conversions for base36 and below.
  • zend-server 2.6.0 adds support for unwinding {@inheritdoc} annotations, and fixes a misleading exception in reflectFunction.
  • zf-development-mode 2.1.2 fixes the factory to pull and set the configuration caching rules under the correct configuration key.
  • zend-expressive-helpers 1.2.1 adds the protected method getRouteResult(), to allow extensions access to the route result instance.
  • zend-expressive-helpers 1.3.0 adds a new general-purpose BodyParamsMiddleware, for parsing the request body and returning a new instance populated with the parsed body parameters. The solution uses a strategy pattern, allowing developers to provide additional strategies per their application needs.

ZF3 Refactors

Since the last update, the following components have been refactored to work with the planned v3 versions of zend-servicemanager and zend-eventmanager. Please note that no new versions have been released at this time; all work remains either in pull requests or in the develop branches of each component.

Component Installer

One idea floated for helping the goal of reducing dependencies in both zend-mvc and the zf2 meta-repository is to have components also act as modules. This would allow them to provide configuration, factories, and event listeners to the MVC runtime in a completely opt-in fashion. The one problem with the approach, however, is automating registration with the application.

To this end, we created a component installer. This package provides composer post un/install scripts that look for metadata in the package; if the metadata is present, the script adds an entry to the application's module list. Components are added to the top of the list, and modules to the bottom.

The new package can be installed as a global composer utility, or downloaded as a self-updateable PHAR file. We will begin updating components to expose themselves to this tooling soon, and update the application skeleton with the scripts as generated by the package, to automate the facilities for greenfield projects.

Expressive Release Candidate

Today, we issued a new release candidate of Expressive, RC5. Be sure to read the announcement to find out what changes have been made! The bulk of the work has gone into expanding the documentation to cover common use case scenarios.

Until next time

The winter holidays are upon our team at this time, and we do not expect much progress in the coming two weeks. Look for updates in January!

Until then, if you want to help:

Many thanks to all the contributors who have provided feedback, patches, reviews, or releases!

Source

The Zend Framework community is pleased to announce the immediate availability of Expressive 1.0.0rc5!

You can install it using Composer, using the create-project command:

$ composer create-project zendframework/zend-expressive-skeleton:1.0.0rc5@rc expressive

You can update your existing applications using:

$ composer update

Depending on what features you're already using, you may have nothing to do, or a few changes you may need to make; see below for more information.

Changes in RC5

The majority of the changes for RC5 were documentation additions, including chapters on:

  • how to serve Expressive from a subdirectory of the web root.
  • how to create modular Expressive applications.
  • how to parse body parameters using new middleware from zend-expressive-helpers.

Two larger changes were made, however:

  • As noted above, zend-expressive-helpers now provides middleware for parsing the request body into parameters.
  • The skeleton and installer now use a new container-interop version of Pimple to ensure users can use Pimple v3, versus our previous support for only v1.

Body parameter parsing

PSR-7 provides facilities for retrieving the parsed body parameters. Most implementations will populate this with the contents of $_POST by default, but for cases where non-form submissions or non-POST submissions are present, you need to parse and populate the body parameters manually.

zend-expressive-helpers now provides middleware for doing this, Zend\Expressive\Helper\BodyParams\BodyParamsMiddleware. This middleware can be optionally added to your application, and supports the addition of custom strategies to allow parsing arbitrary content types.

This functionality is completely opt-in, and will be available following a composer update within your application.

Read more about it in the documentation.

Pimple upgrade

As noted, our previous Pimple support was for v1, which is unsupported at this time. We decided to upgrade our support to the latest stable version, v3, prior to the stable release of Expressive.

For those of you who were using Pimple previously, if you wish to update your application, you will need to do the following:

  • First, remove the previous pimple support: composer remove mouf/pimple-interop pimple/pimple.
  • Second, add the new v3 interop support: composer require xtreamwayz/pimple-container-interop.
  • Third, replace the contents of config/container.php with the contents of the linked skeleton file.

After taking those steps, you should see everything working just as it did before.

zend-view changes

One trivial change was made to the layout template for zend-view users: instead of using headScript(), inlineScript() is now used, and emitted at the end of the <body> section of the layout. This is a slight front-end performance enhancement; if you are using the default layout, we recommend updating accordingly.

Future

At this point, we do not anticipate any more code changes before the stable release. We are waiting on at least one pull request for an additional cookbook recipe, and highly recommend users dive into the documentation and help us polish it for the final release. Suggestions already include flow and architecture diagrams; if anybody wants to create these, we'll happily take them!

If you are testing Expressive — whether for the first time, or updating an existing application — please help us prepare it for general availability!

Source

Per our previous ZF3 update, this is the first in an ongoing series of bi-weekly posts on ZF3 development status.

The highlights:

  • >80 pull requests merged
  • 28 releases of components
  • 9 components updated to zend-servicemanager/zend-eventmanager v3 changes
  • 2 release candidates of expressive

Pull request activity

Marco Pivetta noted yesterday on twitter:

Receiving around 15 mails/hour from zendframework repositories: work is going on at full speed :O #zf2 #zf3

@Ocramius (link)

Activity has been quite high the past couple weeks, with more than 80 pull requests merged (link requires a GitHub account). Many of these were related to the Expressive release candidates (more on those later), but more than half were on ZF components, and ranged from bugfixes to new features to ZF3-specific refactors.

Component Releases

We released the following components and versions since the last update. While not all releases are related to ZF3 specifically, this list is intended to detail activity within the organization. One goal of splitting the various components was to increase release velocity; we're definitely seeing that happen!

  • zend-diactoros 1.2.0, which adds a TextResponse and CallbackStream, updates the SapiEmitter to emit a Content-Length header by default, and ensures the default charset of an HtmlResposne is utf-8.
  • zend-code 2.6.1, which replaces the doctrine/common dependency with the more specific doctrine/annotations.
  • zend-expressive-template, a new component containing the TemplateRendererInterface and related value objects used by Expressive; this allows developers to use the interface in non-Expressive applications.
  • zend-expressive-router, a new component containing the RouterInterface and related value objects used by Expressive; this allows developers to use the interface in non-Expressive applications.
  • zend-expressive-aurarouter 1.0.0 (0.3.0 was also released); the component now depends on zend-expressive-router instead of Expressive, and is considered stable.
  • zend-expressive-fastroute 1.0.0 (0.3.0 was also released); the component now depends on zend-expressive-router instead of Expressive, and is considered stable.
  • zend-expressive-zendrouter 1.0.0 (0.3.0 was also released); the component now depends on zend-expressive-router instead of Expressive, and is considered stable.
  • zend-expressive-platesrenderer 1.0.0 (0.3.0 was also released); the component now depends on zend-expressive-template instead of Expressive, and is considered stable.
  • zend-expressive-twigrenderer 1.0.0 (0.3.0 and 0.3.1 were also released); the component now depends on zend-expressive-template instead of Expressive, and is considered stable. Additionally, the component now has a new configuration structure.
  • zend-expressive-zendviewrenderer 1.0.0 (0.3.0, 0.3.1, 0.4.0, and 0.4.1 were also released); the component now depends on zend-expressive-template instead of Expressive, and is considered stable. Additionally, the component now has custom url and serverUrl helpers that work with zend-expressive-router and PSR-7, respectively.
  • zend-feed 2.6.0 provides improvements that reduce dependencies, and allow better interoperability with other HTTP clients; including PSR-7-based clients.
  • zend-expressive-helpers, a new component that provides helpers for generating URI paths from configured routes, and fully-qualified URIs based on the current request URI.
  • zend-test 2.5.2 adds support for writing tests to use PHPUnit 5.
  • zend-eventmanager 2.6.1 updates the dependencies to make Athletic a development-only dependency.
  • zend-db 2.6.2 provides a number of bugfixes
  • ZendService_Apple_Apns 1.1.2 and 1.2.0, providing a bugfix and Safari push support, respectively.

ZF3 Refactors

Since the last update, the following components have been refactored to work with the planned v3 versions of zend-servicemanager and zend-eventmanager. Please note that no new versions have been released at this time; all work remains either in pull requests or in the develop branches of each component.

Expressive Release Candidates

This week, we've issued two release candidates of Expressive, with RC4 being the latest. Be sure to read the RC3 and RC4 announcements to find out what changes have been made; a lot of work has occurred in the past few weeks!

Until next time

We'll be providing another update on either 22 or 23 December 2015 (based on holiday vacation schedules).

Until then, if you want to help:

Many thanks to all the contributors who have provided feedback, patches, reviews, or releases!

Source

The Zend Framework community is pleased to announce the immediate availability of Expressive 1.0.0rc4!

You can install it using Composer, using the create-project command:

$ composer create-project zendframework/zend-expressive-skeleton:1.0.0rc4@rc expressive

If you're already using Expressive, read below for how to update your application!

Changes in RC4

The majority of the changes for RC4 centered around polishing the skeleton and providing more documentation. One change, however, represented a bugfix, and will impact existing installations that were making use of the UrlHelper from the zend-expressive-helpers package.

Changes in this release include:

Updates to UrlHelper registration

Two separate reports indicated that the methodology chosen for registering Zend\Expressive\Helper\UrlHelper as a route result observer with the Application instance was not viable. In one case, a circular dependency issue was discovered; in the other, the UrlHelper instance was retrieved for the first time too late to be triggered as a route result observer.

To solve this, we chose a path similar to the ServerUrlHelper: dedicated middleware that, on invocation, registers the UrlHelper with the current Application instance (or any Zend\Expressive\Router\RouteResultSubjectInterface implementation). For existing users, this will require both upgrading your zend-expressive-helpers version, as well as some minor changes to your configuration; see the Upgrading section below.

Updates to the default source structure

Prior to RC4, the composer.json mapped the App namespace to the src/ directory, and the AppTest namespace to the test/ directory. We felt that this provided an unreasonable limitation on application structure, and decided to change it as follows:

  • We created the directory src/App/.
  • We pushed the src/Action/ directory to src/App/Action/.
  • We created the directory test/AppTest/.
  • We pushed the test/Action/ directory to test/AppTest/Action/.
  • We updated the autoloading entries in composer.json to map the App and AppTest namespaces to the new subdirectories.

The changes allow you to have multiple top-level namespaces under the src/ directory, and will help encourage a modular structure (similar to ZF2 modules, Symfony bundles, Laravel packages, etc.).

Composer "serve" command

To simplify serving your application via the built-in PHP web server, we have added a Composer script named "serve", which simply executes php -S 0.0.0.0:8080 -t public/. You can invoke it as:

$ composer serve

Caching simplification

In the skeleton application, we allow you to opt-in to configuration caching. Prior to RC4, cached configuration was saved as a JSON serialized string; with the update to RC4, it is now cached as a PHP file, allowing it to be pulled in via include(). This approach is both simpler and more performant. Again, the Upgrading section below will detail how to modify your existing installation to make this change.

Twig configuration updates

Version 0.3.0 of zend-expressive-twigrenderer made changes to the configuration format for Twig users. While the old configuration can still be used, RC4 updates the default configuration to follow the new recommended structure.

zend-view configuration updates

Version 0.4.0 of zend-expressive-zendviewrenderer (zend-view integration) added the ability to consume a configured Zend\View\HelperPluginManager service, when available, and also provides a factory for it. Additionally, that factory allows using the top-level view_helpers key to provide additional plugins (using standard zend-servicemanager style configuration).

RC4 of the Expressive skeleton updates the default zend-view configuration to register the HelperPluginManager, and to define the top-level view_helpers configuration key.

Cross-platform documentation

The "usage examples" section of the documentation has a section on "Hello World Using a Configuration-Driven Container". This documentation detailed using PHP's glob() function to aggregate configuration files. However, glob() does not work identically on all platforms.

The documentation has been updated to use Zend\Stdlib\Glob::glob(), which is a cross-platform shim for glob().

Cookbook entries

Two new entries have been added to the cookbook, one for configuring zend-view to use helpers from other components (such as zend-form), and another detailing how to add and configure custom zend-view view helpers.

Upgrading

If you're already using Expressive, you'll want to upgrade! To do so, you'll need to make a few changes to your application.

Dependency updates

  • You'll want to update zendframework/zend-expressive to RC4; this should happen on a composer update.
  • You'll want to update zendframework/zend-expressive-helpers to ^1.2, if you are using them.

Configuration changes

Configuration changes are only necessary if (a) you are upgrading from a previous release candidate, (b) using the UrlHelper, and/or (c) using Twig or zend-view.

UrlHelper changes

For the UrlHelper, you will need to make the following additions to the config/autoload/middleware-pipeline.global.php file:

use Zend\Expressive\Helper;

return [
    'dependencies' => [
        'factories' => [
            /* ... */
            Helper\UrlHelperMiddleware::class => Helper\UrlHelperMiddlewareFactory::class,
        ],
    ],
    'middleware_pipeline' => [
        'pre_routing' => [
            // This entry was originally just for the ServerUrlMiddleware;
            // make it an array listing both that and the UrlHelperMiddleware,
            // as below:
            [
                'middleware' => [
                    Helper\ServerUrlMiddleware::class,
                    Helper\UrlHelperMiddleware::class,
                ],
            ],
            /* ... */
        ],
        'post_routing' => [
            /* ... */
        ],
    ],
    /* ... */
];

Twig changes

In the Twig configuration file, config/autoload/templates.global.php, originally the structure was as follows:

return [
    'dependencies' => [ /* ... */ ],
    'templates' => [
        'extension' => 'html.twig',
        'cache_dir' => 'data/cache/twig',
        'assets_url' => '/',
        'assets_version' => null,
        'paths' => [
            'app' => ['templates/app'],
            'layout' => ['templates/layout'],
            'error' => ['templates/error'],
        ],
    ],
];

While this will continue to work, we recommend updating to the following structure:

return [
    'dependencies' => [ /* ... */ ],
    'templates' => [
        'extension' => 'html.twig',
        'paths' => [
            'app' => ['templates/app'],
            'layout' => ['templates/layout'],
            'error' => ['templates/error'],
        ],
    ],
    'twig' => [
        'cache_dir' => 'data/cache/twig',
        'assets_url' => '/',
        'assets_version' => null,
        'extensions' => [
            // extension service names or instances
        ],
    ],
];

zend-view changes

If you are upgrading from a previous release candidate, we recommend making the following changes to your config/autoload/templates.global.php file:

return [
    'dependencies' => [
        'factories' => [
            /* ... */
            Zend\View\HelperPluginManager::class =>
                Zend\Expressive\ZendView\HelperPluginManagerFactory::class,
        ],
    ],

    'templates' => [
        /* ... */
    ],

    // Also, add this key, to provide a place to register view helpers:
    'view_helpers' => [
        'aliases' => [ /* ... */ ],
        'invokables' => [ /* ... */ ],
        'factories' => [ /* ... */ ],
        // add other keys as necessary
    ],
]

Autoloading/structure changes

If you want to bring your application fully up-to-date with the expressive skeleton, you may want to consider creating a top-level src/App/ directory, and pushing your Action/ and other subdirectories under it, and updating the App\\ namespace autoloading entry in composer.json to point to the new directory:

# source trees become:
src/
    App/
        Action/
test/
    AppTest/
        Action/

and the autoload and autoload-dev sections of composer.json become:

"autoload": {
    "psr-4": {
        "App\\": "src/App/",
    }
},
"autoload-dev": {
    "psr-4": {
        "AppTest\\": "test/AppTest/",
    }
}

The above will allow you to start considering your middleware as discrete units of functionality, and potentially allow you to port them betweeen applications.

Future

In just two days, we've had quite a large number of users reporting their feedback, and we're quite pleased that the majority of the work done for RC4 centered around documentation! The release has a lot of polish at this point, and we anticipate a stable release in the next couple weeks.

If you are testing Expressive — whether for the first time, or updating an existing application — please help us prepare it for general availability!

Source