ZF3 in a nutshell
Emphasis on components
Focus on HTTP, via PSR-7 and middleware
Optimize for PHP 7 , but support PHP 5.5+
Stable release October 2015!
Components
ZF1: the past
Components are developed within the framework
repository, and
are installable only with the entire
framework .
ZF2: today
Components are developed within the framework
repository, and
can be installed individually
(Composer, git submodules).
"Individually" is a loose term; most components have several
dependencies currently.
This is accomplished via a semi-manual process (we trigger it
for each release).
If a patch lands in a component, you can only test it in your
application before a release if you add all of
ZF as a dependency.
The future
ZF 2.5+
Components will be developed in their own repositories.
Components will be installable individually.
The ZF repository will depend on components!
We'll be focusing on separated interfaces as well, to better
decouple components, allowing them to be used
independently.
ZF's composer.json becomes...
{
"require": {
"zendframework/zend-authentication": "^2.5",
"zendframework/zend-cache": "^2.5",
"zendframework/zend-captcha": "^2.5",
"etc": "*"
}
}
Ease maintenance
Allow more teams with commit rights
Allow deterministic fate of repositories
If a repo has no contributors, and isn't receiving issues/pull
requests, we may determine in the future to abandon it.
Selective evolution
Bump major versions as needed
Framework repo can selectively upgrade
components
Some components need more changes than others: SM, EM,
InputFilter, Forms.
Others are stable, and may not need huge changes in the
future: Escaper, Config, Paginator, etc.
Let them evolve on their own timelines; the framework can
upgrade them selectively.
Use-case specific skeletons
Delivering only web services?
Need performance?
Need everything?
There will be a skeleton for
that!
If you're only doing SOAP, XML-RPC, or JSON-RPC, you might do
a small subset of components. Or if you're doing REST, you might
omit things like Navigation, Form, XmlRpc, Soap, and
session.
If you're focusing on performance, you might do a different
subset.
HTTP, PSR-7, and Middleware
HTTP is the foundation of the web
A client sends a request
A server returns a response
HTTP messages
Request
GET /path HTTP/1.1
Host: example.com
Accept: application/json
Response
HTTP/1.1 200 OK
Content-Type: application/json
{"foo":"bar"}
Frameworks model messages
But every framework does it differently.
$method = $request->getMethod();
$method = $request->getRequestMethod();
$method = $request->method;
PSR-7
Shared HTTP Message Interfaces
Request
$method = $request->getMethod();
$accept = $request->getHeader('Accept');
$path = $request->getUri()->getPath();
$controller = $request->getAttribute('controller');
Response
$response->getBody()->write('Hello world!');
$response = $response
->withStatus(200, 'OK')
->withHeader('Content-Type', 'text/plain');
PSR-7 and the ZF MVC
Still under discussion, but…
we may consume PSR-7 directly
or create a bridge implementation
Bridging would happen in order to retain our current API,
while manipulating a PSR-7 instance underneath. This would give
us compatibility with both worlds, and make for an easier
migration path. PSR-7 users would still be supported.
Middleware
Between the request and response
function (Request $request, Response $response)
{
// do some work
return $response; // same, or a new instance.
}
Stacks or pipelines
$pipeline->pipe($middleware1); // always evaluate
$pipeline->pipe('/path', $middleware2); // only if path matches
$pipeline->pipe('/different/path', $middleware3);
$response = $pipeline->run();
This is like Connect in node.js
Onion style
class Outer
{
public $inner;
public function __invoke($request, $response)
{
// do some work
$response = ($this->inner)($request, $response);
// do some work
return $response;
}
}
$response = $outer($request, $response);
This is like Rack and WSGI
Lambda style
function (Request $request)
{
// do some work
return $response;
}
$response = $middleware($request);
This is a functional paradigm
Laravel 5 uses this style
Consuming middleware
ZF will allow dispatching the following middleware:
/**
* @return Response
*/
public function (Request $request, Response $response);
… and ZF controllers will be middleware.
ZF's DispatchableInterface is essentially this middleware
interface already.
Middleware wrapper for ZF
$middleware = new MvcMiddlewareWrapper(
require 'config/application/config.php'
);
class MvcMiddlewareWrapper
{
public function __invoke($request, $response)
{
$app = Application::init($this->config);
return $app->dispatch($request, $response);
}
}
Request/response are PSR-7 messages
We'll likely do something like this for ZF1, too, which can
bridge the request/response instances.
Requires we have a new path that returns the response, instead
of emitting it.
Lazy-initialization so that it only loads ZF if the middleware
is invoked!
Middleware as an alternative runtime
Why?!?!?!?!
Performance
Developer experience
Reusability across frameworks
Performance: lazy-loading of resources based on opportunistic
path matching; slimmer runtime engine (typically). You **can**
run into the same performance issues of any web application;
it's a matter of how you architect things.
DX: simpler patterns; usually do only one thing per
middleware; compose middleware in order to accomplish complex
workflows; etc.
If you target middleware, and not the framework, you create
reusable web-facing widgets!
Example
$app = new Middleware();
$app->pipe('/', $homepage); // Static!
$app->pipe('/customer', $zf2Middleware); // ZF2!
$app->pipe('/products', $zf1Middleware); // ZF1!
$app->pipe('/api', $apigility); // Apigility!
$app->pipe('/user', $userMiddleware); // 3rd party!
$server->listen($app);
PSR-7 and Middleware provide…
Paths for performance optimization
Simpler web-facing interfaces
Greater interoperability and re-use potential
PHP 7 and PHP 5.5
Upgrade to PHP 5.5
We get to use traits!
We get to use short array syntax!
We get to use the callable type hint!
We get to use finally !
We can use the ::class magic constant!
We get to use generators!
We get faster, more secure PHP!
PHP 7
Impressive performance improvement!
New data structure management in the PHP engine
New features like return/scalar type declarations
PHP 7: benchmark
$a = array();
for ($i = 0; $i < 1000000; $i++) {
$a[$i] = array("hello");
}
echo memory_get_usage(true);
PHP 5.6
PHP 7
Memory Usage
428 MB
33 MB
Execution time
0.49 sec
0.06 sec
bench.php
Wordpress
Frameworks
ZF3: optimized for PHP 7
Running tests in strict and/or coercive mode.
Allowing us to fix bugs for PHP 5, and also forward-proof
code for PHP 7.
Potentially automate release builds that add
scalar typehints from docblock annotations.
Profiling in PHP 7 to see where we can optimize
architecture for performance.
The last is important, as a lot of work hsa been done in PHP 7
to streamline the object call graph; if we profile early, we can
make changes that will benefit PHP 7 users specifically.
Updating PHP…
Provides better security
Improves performance
Allows us to improve the framework
Components!
Welcome to a true component library, built
with Composer in mind!
HTTP, PSR-7, and Middleware!
Welcome to a truly HTTP-centric framework,
utilizing the best enterprise stack alongside
an optimized middleware runtime!
PHP 7 and PHP 5.5!
Welcome to the future of PHP, using the
latest and greatest features in order to
deliver you a better, more secure , more
performant runtime!