February 17th, 2010

#slive2010 Liveblogging: Fabien Potencier: Symfony 2.0

Tom Boutell
Chief Software Architect
I am liveblogging Fabien Potencier's Symfony 2.0 presentation. Bear with me and my editorial errors, simplifications and bare-faced libels.

My own opinions are in parentheses.

They are setting up now.

"Symfony 2.0 Reloaded" Preview Release

"I've decided to do the session in French" heh

In 10 minutes you will discover the shiny new version of Symfony, Symfony 2.0. Symfony 2 is just awesome. But first a bit of history.

Symfony 1.0 released in January 2007. Started as glue between existing libraries: Mojavi, Propel, Pardo i18n, ...

"How many of you are still using 1.0?" [Some hands go up] "Ohhhhh!" [Hey, I raised my hand too, I have to support existing projects after all, heh. Our new stuff is all 1.4]

With Symfony 1.2 in November 2008, decoupled but cohesive components wre rolled out: forms, routing cache, YAML, ORMs... but still the same core.

Symfony 1.4 - November 2009. Added polish on existing features. Removed the support for deprecated features. Current LTS released, maintained until late 2012.

What is Symfony 2.0? The next version of course... except Symfony now takes an 'S' instead of an 's'. That's the big difference!

Talk about Symfony 2 with a capital S please! Symfony 1 (uppercase) does not make any sense, symfony 2 does not make sense! It's all about Symfony 2. "I'm quite picky."

"Same philosophy, just better." We've learned a lot from our mistakes. We've learned a lot... we have problems with Symfony 1, but not all are fixable. It requires breaking backwards compatibility. So we need to go forward.

Symfony 2 is still an MVC framework.

It's probably more of a Fabien-style framework than anything else (his words not mine (: ).

MTV: Model, Template and View?

Highly configurable and extensible. Same Symfony Components (DI, events, request, etc), same great developer tools, full featured.

Everything is upgraded to PHP 5.3. (Great, I hope they debug PHP 5.3 by the time Symfony 2.0 is complete!)

OK, but why a major version # change then? Because it has a brand new low-level architecture to fix some of the deeper issues with Symfony 1.x.

New best practices and concepts, built with speed and flexibility in mind. Based on dependency injection container, a new plugin system.

Namespaces and anonymous functions will be used.

A Quick Tour
namespace Application\HelloBundle\Controller;
use Symfony\Framework\WeBundle\Controller;


class HelloControlelr extends Controller { public function indexAction($name) { return $this->render('HelloBundle:Hello:index', array('name' => $name)); } }

&lt!-- No magic for layouts this is an explicit layout extension in the template --> <?php $view->extend('HelloBundle::layout') ?>

Hello <?php echo $name ?>!

Layout:

<html> <head>.... <body> <?php $view->slots->output('_content') ?> </body> </html>


Helpers are objects

hello:
  pattern: /hello/:name
  defaults:
    _bundle: HelloBundle
    _controller: Hello
   _action: index


:name becomes the first argument to the action. If you have more in the route, they become additional arguments to the action. No $request parameter.

Extremely Configurable

Why? Because it is all managed by a Dependency Injection Container. "I won't talk about the DI container today" (aw, I wish someone had explained it this week; it was taken as a given by an earlier presentation today; I've read about it but many haven't had a chance yet I'm sure).

The DI Container replaces "a lot of symfony 1 things:"

sfConfig All config handlers sfProjectConfiguration sfContext (no singleton anymore!) The configuration cache system (!!) And some more

In one easy-to-master, unified, and cohesive package.

databases.yml can be renamed. You can create just one big config file if you want, or have several small ones.

Name your configuration files any way you want. Use PHP, XML, YAML or even INI format.

You can do raw PHP rather well:

$configuration = new BuilderConfiguration();
$configuration->addResource(new FileResource(__FILE__));


$configuration->mergeExtension('web.user', array('default_culture' => 'fr', 'session' => array('name => 'SYMFONY')...); etc


Same thing shown in YAML and XML. XML syntax is rather consistent, not much more verbose than YAML anymore.

$configuration->mergeExtension('swift.mailer', array('transport' => 'gmail', 'username' -=> 'fabien.potencier', 'password' => 'xxxxxx', ... ));


XMLNS schema definitions for lots of things

Autocompletion based on schemas demonstrated in NetBeans IDE

Inherit configuration as much as you want

You can have a master configuration and then configurations for each environment for instance. Symfony 1 had several defined levels. Framework, project, application, module.

In Symfony 2 it's up to you. You can have as many as you want, and mix and match config files written in different formats, which is useful when using third-party plugins.

<imports>
<import resource="parent.xml" />
<import resource="config.yml" />
<import resource="parameters.ini" />
</imports>


<zend:logger priority="debug" />

<web:debug toolbar="%kernel.debug" ide="textmate" />


Which format to use? Internally they only use XML because it has autocomplete, validation, help etc. etc. due to schemas. Fabien endorses XML.

Store Sensitive Settings Outside Of Your Project (database passwords... clever rsync_exclude tricks go away?)

Old way (in 2 syntax):

<doctrine:dbal
dbname="sfweb"
username="root"
password="HeyThisIsTotallyPublic"
/>


New way:

password=%SYMFONY_DOCTRINE_DBAL_PASSWORD%

And set:

SetEnv SYMFONY_DOCTRINE_DBAL_PASSWORD "foobar"

(is that literally a shell thing?)

Creating DIC Extensions Is Insanely Simple

Very fast thanks to a smart caching mechanism - always knows when to flush the cache (!)

Whenever you do something that requires creating the cache, Symfony knows it must flush and recreate the cache.

The code in the cache is PHPDoc, seriously readable code

The code to fetch something from the DIC is as fast as the code you'd write yourself (he showed us; there are no unnecessary layers of cruft)

The DIC can manage any PHP object: POPO (?)

"Plugins..."

Good in 1.x, better in 2.0

"So much better we need a new name." They are now called Bundles.

Why? Because they are first class citizens in Symfony 2.0. In Symfony 1, they added the plugin system late in the game. They had applications and plugins and there was a question as to what should be what. In 2.0 everything is a bundle. Core features, third-party code, application code. The framework itself is made up of bundles. Doctrine is a bundle, etc.

Default directory structure:

app/ src/ web/

You don't have to adhere to it.

app/
  AppKernel.php
  cache/
  config/
  console
  logs/


src/ autoload.php Application/ Bundle/ vendor/ doctrine/ swiftmailer/ symfony/ zend/


Note that Zend is on the shortlist, but in "vendor" (and so is symfony).

web/
  index.php
  index_dev.php


Controllers.

A bundle dir looks like this:
.../
  SomeBundle/
  Bundle.php
  Controller/
  Model/
  Resources/
    config/
    views/


Templates, data, views, configuration, js, etc. live in Resources.
public function registerBundleDirs()
{
  return array(
    'Application' => __DIR__ . '/../src/Application',
    same for bundle
    similar for Symfony Framework pointing to its bundle dir, giving it a prettier name on the left, using namespaces
}


$this->render('SomeBundle:Hello:index', $params)
SomeBundle is the bundle's declared name, not something based on position in the filesystem. Looks for a matching bundle (much as it now looks for modules in plugins and the app).

Could be in:

Applciation\SomeBundle Bundle\SomeBundle Symfony\Framework\SomeBundle

Extend things by making one that appears earlier on that list.

In Symfony 1 to extend a plugin you must muck about with a BaseaActions class to make aActions extensible. In Symfony 2 it is natural. Just create another bundle. (? How does a bundle extend a bundle exactly? Is it about the order you register them in? Are you extending classes or is this a DI trick?)

"Less concepts... but more powerful ones"

Symfony 1 View Layer

A layout is just another tempalte with __content as a special slot

A partial is just at emplate you embed in another one

A component is just another action
<?php $view->output('BlogBundle:Post:list', array('posts' => $posts)) ?>


<?php $view->actions->output('BlogBundle:Post:list', array('limit' => 2)) ?>


So back to the layout... _content is just a slot now, not something special.

Big and small improvements.

Multiple levels of layouts. You can extend the template, but you can also extend the layout as much as you want... partials can be decorated too. Better logging.

INFO: Matched route "blog_home" (parameters: array('_bundle' => 'BlogBundle' ....))

Errors are called out better with an ERR prefix (there were supposed to be multiple levels in 1.x right?)
<zend:logger priority="debug" />


Great exception error pages

They integrate with your editor if you have the symfony firebug bar, very nice

"Content of the Output" available in the event of an error! Big improvement over 1.x. You can see the var_dumps before the error etc.

"An Even Better Web Debug Toolbar" (oops it was "Event Better" I was very puzzled (: )

The web debug toolbar is at the bottom of the page. You can look at it when you want to, otherwise out of your way.

"Everythign you need is at the bottom of the screen."

symfony 2.0.0-DEV php 5.3.1/xdebug/accel blog/dev/debug default/html/200/text/html 6ms 1280kb [db] 0

"default" is the route that matched.


Check out Apostrophe, our Symfony-based Content Management System!

2.x is web designer "friendly." No more apps/frontend/modules/foobar/templates before you can find what you are working on. You can have one templates folder.

app/
  views/
    BlogBundle/
    Post/
      index.php
 And then other bundles with their subfolders


(That looks familiar actually...? But he's saying there is one templates dir...? Ah because a bundle is equivalent to a plugin not just a module. All templates for a plugin-scale thing are now in one folder)

Symfony 2 Is A Lazy Framework
use Symfony\Foundation\UniveralClassLoader;


$loader = new UniversalClassLoader(); $loader->registerNamespaces(Symfony, Application, Bundle, Doctrine with their root paths in a hash)); $loader->registerPrefixes(array('Swift_' ... ));


Lazy-loading of services

In 1.x factories are created by default. No choice. In 2.x, if you don't use a user object, you won't get one. If you don't need request, you don't get it.

Lazy-loading of listeners

A bunch of events, a lot of different listeners. In Symfony 2 we only create listeners if an event is notified. You can register as many listeners as you want, the overhead is small.

Lazy-loading of helpers
<?php echo $view->router->generate('blog_post', array('id' => $post->getId())) ?>


The router helper doesn't get created unless I use it.

(Note that $view is a new variable present in view layer code like partials and templates. Helpers are objects, and view itself is an object. No more pretending you don't need -> in templates (we all used it anyway with the model).)

Symfony 2 routing system has similar features but the implementation is very different. Compiles down to plain PHP code.

You can use Apache for Routing matching for extreme speed (!).

A Very Fast Development Environment

Again, no more clear cache, it's automatic in dev environment. A metafile references the files that are relevant to the cache, and when they get touched Symfony can check very quickly whether it must clear the cache.

You can also stash routes in a db, and Symfony also knows if it needs to rebuild based on that.

And that's Symfony 2, "we have barely scratched the face" of Symfony 2.0.

Easy to learn Easy to use Extensible at will

"People will tell you that Symfony 1 is slow, hard to learn, complex. I think they are wrong. But I think Symfony 2 is easy to learn, easy to use, and extensible at will. I want to lower the barrier to entry of Symfony 2.0. I want it to be usable for very small websites and very big ones. I want people to be able to grasp Symfony 2.0 in a matter of minutes. Probably 20 minutes. I want people to be able to understand and be fluent in a matter of hours. Perhaps a day, not more. Everything is more explicit. Less what-the-fuck effects" (borrowing Jon Wage's line from yesterday heh). "You can change everything in Symfony 2.0. If something is not tasty enough for you, you can swap the component and use something else. You can change the whole directory structure if you want, create a whole application in one file if you want. You should be able to guess new concepts without reading the documentation, guess the thing you don't know. That's possible because we have fewer concepts. Done with two or three concepts, easier to guess how it works and how it would work for your specific case.

Of course we have all of the great features of Symfony 1...

But Symfony 2 should be slow right? No. It is Fast as hell This is the fastest framework ever created. It can be seven times faster than any other framework for a simple hello world application but I don't care. The last time a customer asked for a hello world application was in the early nineties so that benchmark does not make sense. So I created a benchmark with a more typical application using all the layers of a typical framework. Models, views, controller, routing. I did benchmarks on a simple application. It's a hello 'name' application, so there is a route, /hello/someone. There is a layout with 15 links and a menu with 15 routes... there are partials.

So we use templates and partials (setTemplate()), links for the routing, layout, but no session or database in this case. We are trying to measure the speed of the framework itself.

If you do this, Symfony 2.0 is 2x faster than Solar 1.0.0, the fastest framework for simple applications. So that's great.

Symfony 2.0 is 2x faster than Symfony 1.2, 2.5x faster than Zend, 4x faster than Lithium, 6x faster than CakePHP 1.2.6. 60x faster than Flow3 (and by the way notice that this means Symfony 1.x is pretty fast relative to most of these).

Symfony 2.0 uses half the memory needed by both Symfony 1 and Zend Framework. Scales better than any other framework.

Stuff still missing:

Controller's nice default pages. Cache via ZF - DI extension coming soon. Form/Validation/Widget: can use 1.4 version for now. Admin generator, ditto. Doctrine 2.0 needs its upper layers but the DBAL layer is already impressive. There is no handy bundle installer yet.

Not for production projects yet, quite stable but he needs to be able to change his mind and make big changes for now. Final release date 2010.

For bleeding edge news (ha!) follow @fabpot, and also on Github, github.com/fabpot.

He's going to release the code (pull a copy?) live.

He's on a Mac too small for him to access the usual VPN icon so he's asked the audience for help finding it through system preferences hee! Good he found it. We'll see if the network works for him...

He's going through the ugly validation of the wifi here... "what-a-fuck?"

"Okay so you won't have the code today... Sorry about that. No, I'll do my best to push the code in about an hour. I will also deploy symfony-reloaded.org, a temporary website about Symfony 2.0.

I can tell you that at the end of the tutorial, you will be able to create great applications with Symfony 2.0. I am a bit frustrated now because I have so many things to tell you. I really think Symfony 2.0 is awesome. So if you have any good questions..."

Standing Ovation

Q. "Are you trying to reinvent Zend Framework 1.0?" Heh. This is a reference to a dumb question asked of Jon Wage yesterday. If I heard right.

Q. "How can we balance future development on 1.x and the new 2.0? What should we do [now] as community working on Symfony framework?"

A. If you start a new project today use 1.4. If you respect best practices and separate model view and controllers and controllers are thin and model is fat and well-coupled templates it will be easier to migrate to 2.0. Don't try to use 2.0 for a site deploying before end of the year. It's too early. But Symfony 2 is so flexible. We will find ways to ease the upgrade path. You can also move to PHP 5.3 today.

Q. About bundle loading: one of the targets is less magic but you first look at the application bundle and things like that. Why keep that sort of magic?

A. It's not magic at all.

Q. It's not exclusive.

A. It is. You need... a small amount of magic. Just a small amount. But you can change the directories, the name of the namespaces, you can have just one namespace if you want.

Q. Can you have sub-bundles without the project level having to know about them explicitly? Can you put a bundle into another bundle?

A. Doesn't make sense. Too complex. You can... yeah why not? Not a big deal... doesn't feel right.

Q. (Me): If I write a bundle, and someone wants to extend an action in my bundle, how do they do that?

A. They just extend your class, and make sure their bundle loads first. (I think I get it: now that we get to declare functional names for our stuff, independent of class names, there's no barrier to extending someone else's class and using the same functional name so it replaces it. As for loading order, you can have more than one bundles folder and call one of them 'overrides' and put it first, or similar.)

Q. Will there be documentation or support soon to help us create bundles that will work for both 1.4 and 2.0?

A. No. Controllers are too different. No more actions.class.php. Very different, with namespaces. You can create a plugin that is also a bundle but there'd be a lot of duplicate code.

Q. But what about the impact on migration of existing code?

A. It's too early to say but there will be great news to announce re: new bundles. One of the problems with Symfony 1 plugins is the quality. We have a lot of plugins for 1.x but a lot of them are just not really usable, to say the least. This will be better. I can't say more right now.

Q. Do we have to enable bundles? Is it possible to set up dependencies between different bundles?

[Fabien opens his sandbox in textmate]

[Points out the registerBundles method seen above]

You need to register bundles.
class Hellokernel extends Kernel
Symfony is now an operating system! Okay no.

Fabien: "if you want, if you want, if you really want..." somebody remix this please (:

... And that's it! Great stuff. Symfony 2.0 will be a big improvement. My next step is to wrestle DI all the way to the ground (:
Tom Boutell
Chief Software Architect