eZ Community » Blogs » Jérôme Vieilledent » eZ Publish 5 from a technical point...

By

eZ Publish 5 from a technical point of view - part 1

Tuesday 10 July 2012 2:52:02 pm

  • Currently 5 out of 5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5

The "Why" and how BC will not kill you

Last week we announced the new synergy between the upcoming eZ Publish 5 and Symfony 2. A lot of technical questions naturally popped out and eZ Engineering will try to address answers to most of them in a series of blog posts, this one being dedicated to our choice and backwards compatibility.

EDITThe next episode of the story is available:  eZ Publish 5 from a technical point of view, Part 2

Why Symfony 2 ?

As explained both in original announcement and Fabien Potencier's blog post, we wanted to focus on our core-skill: Content Management and Customer Experience. Of course we could have built our own HMVC framework, like has been done back with eZ Publish 3.0. But why reinventing the wheel? A couple of good frameworks is available out there, let's just evaluate them and see if they fit our needs! And Symfony 2 was one of the best alternatives, because it's modern, elegant, powerful and all the components are loosely coupled. Besides, it was also a very nice opportunity to open eZ Publish to a huge community! 

Choosing Symfony 2 full stack thus gives the opportunity to significantly increase eZ community with developers who know very well the architecture and with a huge amount of existing bundles (name for Symfony extensions) that are de facto compatible with eZ Publish 5. 

What about Zeta Components?

With the announcement of eZ Publish going with Symfony, some of you were concerned about Zeta Components.

Zeta Components will continue to be used in eZ Publish in the future, but the change is that we only use the one we need, and the one that are clearly better then what is out there. For example, we still use them extensively in strategic part of our API (ezcDatabase being used for instance in the Legacy Storage Engine), and we plan to continue using components like ezcCache.

Zeta Components being developed quite some time ago, it would have needed lots of engineering in some cases to be on pair with alternatives out there today, and competing on a component level is not something we intend to focus on.

Backwards compatibility

When we first began to talk about our first steps towards eZ Publish 5, a lot of people in the eZ community started to be worried. We indeed presented a lot of changes with the new Public API. Those changes were necessary to allow us to significantly improve the performance and the developer experience, but as always with such type of changes, people got scared about migrations and all new stuff to learn from scratch. This is fully understandable and we did hear that.

One of the most frequent questions we had were :

  • Will my old templates continue to work with eZ Publish 5 ?
  • What about all the modules I developed and that I use extensively ?
  • Will my 1.000.000 content objects stay compatible with the new version ?

Time to give clear answers to those questions !

Data model

When we started to develop the new API, one of the pre-requisites was to be 100% data compatible, and we did respect that ! So yes, all your content is safe and will be compatible with version 5.x thanks to the Legacy Storage Engine. To be short, this is a rewrite of the current data model implementation ; we didn't touch anything regarding the database tables.

Templates

With eZ Publish 5, we use Twig as a default template engine. I insist on the default part since, through the Templating component, Symfony allows to use several types of templates at once.

But how could we be compatible with the old eZ Template engine? Twig is fairly modern and has nothing in common with eZTemplate. Well, thanks to some refactoring in the 4.x kernel and some Twig magic, we managed to provide a gateway between Twig templates and old eZ templates, allowing to include old templates into new ones !

{# Twig template #}
{# Following code will include my/old_template.tpl, exposing $someVar variable in it #}
{% ez_legacy_include "design:my/old_template.tpl" with {"someVar": "someValue"} %}

Pretty cool heh ? And of course it's possible to pass any kind of parameters, including objects. They are made displayable in old templates through a generic adapter design pattern implementation. And if you don't find this sufficient, you can still develop object converters !

See fully functional example in the eZ Publish 5 DemoBundle (take a look at the associated controller as well).

Sandboxed legacy kernel

This gateway has been made possible thanks to the eZ Publish 4.x kernel (aka legacy kernel) we refactored and exposed as a service in Symfony. So first yes, it means that eZ Publish 5 still relies on legacy code and it will be the case for several future versions (probably until 6.0). But this code has been completely sandboxed thanks to a big refactoring of index.php (see the difference before and after) and a PHP 5.3 killer feature: Closures.

Note : We're not talking about the sandbox feature in Twig here.

The mechanism we set up is simply to isolate the execution of legacy code within a closure that will be run in the legacy kernel context. Here is an example :

<?php
// Inside a controller/action
$settingName = 'MySetting';
$test = array( 'oneValue', 'anotherValue' );
$myLegacySetting = $this->getLegacyKernel()->runCallback(
    function () use ( $settingName, $test )
    {
        // Here you can reuse $settingName and $test variables inside the legacy context
        $ini = eZINI::instance( 'someconfig.ini' );
        return $ini->variable( 'SomeSection', $settingName );
    }
);

This is exactly what is done for the ez_legacy_include Twig tag (see the implementation).

In the future, it will be also possible to run old modules as sub-requests from a Twig template, and the other way around (from old to new code), allowing to implement new features for the admin interface, which stays in the legacy part for now, with new controllers, taking advantage of all the power of Symfony.

Routing fallback

The last thing I wanted to present in this blog post is the backwards compatibility with old modules. You won't have to rewrite your modules to stay compatible with 5.x ! This is because we implemented a fallback routing mechanism. This mechanism consists of forwarding a request that has not been matched by the new stack to the legacy kernel.

This is as simple as that. You wrote an awesome module that points to /awesomemodule/myview and you didn't migrate it yet to 5.x? No problem, it will continue to work just as before as the new kernel will forward requests to the old one.
And when you're ready to migrate your module to the new kernel (as a Symfony controller then), you'll just have to declare a route like for any regular Symfony controller (read the Symfony documentation on creating pages) !

Performance

What about performance, you may asked? Indeed, all this compatibility layer must have a high cost, you might think.

Well, the impact is actually fairly minimal: approximately 10-15ms per request forward, and this can be further reduced as we integrate the two layers (access matching, sessions, ..).

Conclusion

Backwards compatibility has been one of our most important requirements eZ Publish 5. Of course there is still a lot to do, the code available on Github being a work in progress (be sure to also check out the API repository), but we do our best to ease future migrations.

Start hacking on eZ Publish 5 and give us some feedback !

Proudly Developed with from