One reasons for PHP still being considered slow is a consequence of how it works under web server environment: every time a client sends request, application is initialized from scratch - it runs all the bootstrap code. Bootstrapping is repeated over and over again, for every connecting client.
While this is an obvious waste of resources, it is also very difficult to avoid without rewriting an application under different architecture. Is there anything that could be done to at least reduce impact of application bootstrap, without making any changes to actual application? As it turns out, there is.
Merging class files
Even simple application written in modern, full-stack framework can use 100-200 classes just to show "Hello, World" in the browser. For each of this classes PHP needs to check if file exists, then open it and parse. This creates significant overhead even when opcache is enabled. There's an easy way to go around it though: you can put all classes that used on every request in a single file.
There are at least two frameworks that can merge this files for you: Symfony (via Bootstrap Files) and Zend Framework (via EdpSuperluminal module). Their solutions are difficult to reuse though, as they are tailored to work with given framework.
Using ideas from this projects as a base, I crafted a general solution, that can be used everywhere:
Idea is to let you choose any classes you want, and merge them together. Just as it is done in Symfony, you can automate this process with composer hooks - merged file will be refreshed whenever you update your dependencies.
This is how your config could look like when building Zend Expressive app:
<?php return [ Zend\ServiceManager\Config::class, Zend\ServiceManager\ServiceManager::class, Zend\Expressive\Container\ApplicationFactory::class, Zend\Expressive\Router\Aura::class, Aura\Router\Router::class, Aura\Router\AbstractSpec::class, Aura\Router\RouteCollection::class, Aura\Router\RouteFactory::class, Aura\Router\Regex::class, Aura\Router\Generator::class, Zend\Expressive\Emitter\EmitterStack::class, Zend\Diactoros\Response\SapiEmitter::class, Zend\Stratigility\MiddlewarePipe::class, Zend\Expressive\Application::class, Zend\Stratigility\Route::class, Zend\Expressive\Router\Route::class, Aura\Router\Route::class, Zend\Diactoros\ServerRequestFactory::class, Zend\Diactoros\ServerRequest::class, Zend\Diactoros\Uri::class, Zend\Diactoros\Stream::class, Zend\Diactoros\PhpInputStream::class, Zend\Diactoros\HeaderSecurity::class, Zend\Diactoros\Response::class, Zend\Stratigility\FinalHandler::class, Zend\Stratigility\Http\Request::class, Zend\Stratigility\Http\Response::class, Zend\Stratigility\Next::class, Zend\Stratigility\Dispatch::class, Zend\Stratigility\Utils::class, Zend\Diactoros\Response\HtmlResponse::class, ];
You don't have to worry about order in which you place this classes, nor about their hard dependencies (parent classes, interfaces...) - Class Dumper will add them automatically to the merged file.
Let's assume you put this list in
classes-to-cache.php file. Merging files
together is as easy as running console command:
php ./vendor/bin/dump-classes.php classes-to-cache.php classes.php.cache --strip
--strip switch will ensure that generated file is as small as possible.
Finally, start using cached classes, by including generated file in your
<?php include 'vendor/autoload.php'; include 'classes.php.cache';
Real performance gain can vary depending on number of files cached and your PHP configuration. I've tried it under different conditions, and I've seen improvements ranging from 2% to 10%. Of course if your App does some IO (database access), the end result will be even smaller. On the other hand, efficiency will increase with number of files merged together. Always ensure that OpCache enabled, and that merged file doesn't grow too big (try keeping it below 1MB).
Despite low efficiency in some cases, this optimization is worth considering, as it comes almost for free - create list of classes, update composer.json, and that's it!
PSR-7 is here and is big. Now, more than one month after it was voted, a lot of work has been put into projects supporting this standard. Even though we’re still at the beginning of this great journey, it is exciting to see what is already available, thanks to great work of PHP community.
Watching related projects since the inception of that standard, I will present packages that can serve as foundation for actual applications: HTTP message implementations, dispatchers and micro frameworks.
As you may know, folks from ZF2/Apigility projects keep bringing interesting utility modules, enriching ZF2 ecosystem. Today I discovered small framework/helper for writing console applications: ZF-Console. And, to my surprise, it was based on my own pull request from last year! I was really proud to see that I brought something useful to the community.
There's an important question often rising when working on Zend Framework 2 module:
should I test service factories? After all, they are usually trivial, they create some object
and inject it with dependencies from
ServiceManager. Having one test per factory seems to be an
Better to go one step back, and ask yourself a question: what exactly do you want to test?
I'm happy to present a ZF2 module that handles composing and sending e-mail messages.
Why another module? There are a few of them already available on ZF modules website. However, when I was looking for solution to use in my application, I quickly realized that most of them are either outdated, or they miss features I needed. That's why I decided to write my own.
My intention was to create something powerful, but still simple to use. You an customize e-mail headers, add layout, automatically generate plaintext version of HTML e-mail, and so on. But you can also start composing and sending e-emails from your controllers with just a few lines of code.
Zend\View is pretty advanced rendering engine, with multiple useful features.
It is working nicely within ZF2's MVC stack, where it is automatically configured for you. But how to use it
without full MVC?
This can be useful in some situations: when building Your Own Microframework™, when creating an application
based on ZF2 components, or (in my case) when working on module that is supposed to render something outside MVC flow.
All of this projects can benefit from nested templates, multiple rendering engines, or pluggable architecture of
So, how to do that?
- Extracting single table from huge MySQL dump
- Automated MySQL backup on dedicated server or VPS
- Learning ZF2: Application flow
- Learning ZF2: The Controller
- PHP SDK for CodebaseHQ API
- Rzut okiem na Zend Framework 2: Event Manager
- Twig w praktyce
- Zend Framework i Twig - integracja
- Skróty klawiszowe w NetBeans
- CKEditor: własny motyw graficzny
- Wydajność Zend Framework - cz. 2
- Wydajność Zend Framework - cz. 1
- "Resetujący" CSS i Firebug
- Migracja z Apache do Nginx
- Przykład zastosowania Zend_Auth i Zend_Acl - cz. 2
- Kopiowanie plików z serwera na serwer
After compiling my very first lines of code at the age of 12,
I became passionate about computer science and technology.
Now I'm a PHP developer, enjoying my work as a member of Cleeng team.
Doing some sports in my spare time.
- Aug 28, 18:57
Pushed 1 commit to master at mtymek/class-dumper
- Aug 28, 18:37
Created branch 0.2.0 at mtymek/class-dumper
- Aug 28, 18:37
Released version 0.2.0 of mtymek/class-dumper
- Aug 28, 18:36
Pushed 4 commits to master at mtymek/class-dumper
- Aug 28, 12:45
Created branch 1.0.3 at mtymek/MtZendeskApi
- Aug 28, 12:45
Released version 1.0.3 of mtymek/MtZendeskApi
- Aug 28, 12:45
Pushed 1 commit to master at mtymek/MtZendeskApi
- Aug 28, 12:38
Created branch 1.0.2 at mtymek/MtZendeskApi