Skip to content
Oct 22 11

Symfony Day 11 Cologne

by Sander Coolen

After a tiresome and informative 9 hours at Symfony Day in Cologne I had the plan of writing this post in the ICE back to Amsterdam. Unfortunately the letter S key of the laptop I brought didn’t work. It’s hard writing about Symfony without using the letter S. You can talk about anything, but not Symfony and similar stuff.

It was the third – and last in its current form, as was announced afterwards – Symfony Day in Cologne. Next year it will be succeeded by a Symfony Live event which will be held in a bigger venue and in a bigger city. Berlin!
The current location is the Komed MediaPark; a convention centre at walking distance of the Main Train Station.

After a slow and little bit chaotic start the conference was kicked-off by Igor Wiedler. He talked about Silex. A micro-framework build on top of the Symfony2 components for which he is one of the lead developers. Silex is a lean and mean framework that enables you to map dynamic routes to controllers in a single step. Its lightweight stuff (a single Phar include) to build lightweight apps. Looks quite suitable for prototyping and your personal once-off mini projects.

Next up was Marc Weistroff who had a good talk about clean pragmatic code and some best practices and programming principles. He spoke about Separation of Concerns, a recurring theme throughout the day, probably the fundamental principle behind the Symfony Components architecture.

The third session was a duo talk by Stefan Koopmanschap and Christian Schaefer. Pretentious blatter versus modest and insightful about sums it up. I promise I will actually write a shitload of constructive criticism on Joind.In actually.

After the lunch… no wait… let’s talk about during the lunch:
Eat all the things!

Thomas Rabaix was next to drag us through our lunch dips. Didn’t work. I fought off sleep and almost dozed off a couple of times. The topic was Sonata AdminBunble and could have been an interesting hour. Unfortunately he tried to crank too much in his 60 minutes in which he was more or less summing up functionalities in monotone English with a heavy French accent. Thomas started of by saying: “I didn’t like the Symfony 1 Admin generator…”. Next time please tell us why you didn’t like it and how you did things better in Sonata. The concept and thought processes behind your approach are much more interesting than their outcome.

Following Rabaix was Hugo Hamon talking about the Symfony2 Console component. A good talk in which he gradually build a command-line hangman game to show us the power and extensibility of the new CLI tool. He compared a command (or task) to a controller: input/output versus request/response and promoted refactoring your command line the way you would refactor your controller code. First: just write everything in the controller or command to make it work. Second: move the business logic to where it belongs. Often resulting in just a couple of lines of code in you controller or command. Separation of concerns.

Last speaker before Fabien’s keynote was Richard Miller with a great talk on the evolution of, or maybe to, Dependency Injection. He had a (more or less) real world example of some crappy, highly coupled, piece of code, which he kept on refactoring by removing dependencies (decoupling) until eventually you were left with needing something to inject the dependencies back into your application… wait… what?!

After a failed intermezzo in which they were planning to officially launch SensioLabs Germany with cake and what not, the stage was given to Fabien Potencier. He had a bit of a philosophical lecture on why Symfony2 is more than a classic MVC framework: Symfony2 is a full-stack framework, but Symfony2 is Symfony2 Components too. SymfonyTWO! Wow, it all makes sensio now!

Aug 19 11

Create subclasses of Doctrine_Query for each model class

by Matthias Noback

To make your model code better readable and reusable, it helps to create  custom Query classes which extend Doctrine_Query. For example, when you have defined a NewsItem in your schema, upon running ./symfony doctrine:build-model a NewsItem.class.php and NewsitemTable.class.php will be generated for you. Now, also create a query class for creating NewsItem queries:

class NewsItemQuery extends Doctrine_Query
{
}

Then modify your NewsItemTable class so it looks like this:

class NewsItemTable extends Doctrine_Table
{
  public function construct()
  {
    $this->setAttribute(Doctrine::ATTR_QUERY_CLASS, 'NewsItemQuery');
  }
}

Notice the fact that it says “construct()”, not “__construct()”. It is better not to override the parent __construct() method, but to use this pseudo-construct method, which the parent class calls at the end of the real __construct() method.

The code above means: whenever a new query is created by calling Doctrine_Core::getTable('NewsItem')->createQuery() the NewsItemQuery class should be used, instead of the default Doctrine_Query class.

Now, enhance the NewsItemQuery class, for example in the following way:

class NewsItemQuery extends Doctrine_Query
{
  /**
   * Join the translation
   *
   * @param string $culture The culture for which to join the translation
   * @return NewsItemQuery
   */
  public function joinTranslation($culture = null)
  {
    if (null === $culture)
    {
      $culture = sfDoctrineRecord::getDefaultCulture();
    }

    return $this->leftJoin($this->getRootAlias().'.Translation t WITH t.lang = ?', $culture);
  }
}

Now you can fetch all news items and join their translation by executing this command:

$news_items = Doctrine_Core::getTable('NewsItem')
  ->createQuery('n')->joinTranslation('nl')->execute();

By using a special Query class for each of your models, your code gets more readable, but will also contain less duplicate code, because you don’t have to copy the ->leftJoin(...) line all over your table class anymore.

Aug 19 11

Processing cachegrind files on Windows

by Matthias Noback

Recently I wanted to get some impression of the performance of a certain web page generated by some PHP code written by myself, on top of the Symfony framework and the Apostrophe Now CMS. This was the picture I had in mind:

KCachegrind call graphThis way I could find out if too much time was spent in certain parts of the code.

First I enabled Xdebug (which was already installed on my server) from within the .htaccess in the web directory of my project. I added these lines:

php_value xdebug.profiler_enable_trigger 1
php_value xdebug.profiler_output_dir /project_dir/data/profiler

I created the given profiler output directory and gave it write permissions for the user that runs the webserver.

Then I typed the URL of the page I wanted to profile inside the browser and added ?XDEBUG_PROFILE to the URL. After pressing Enter, I found a cachegrind.out.xxxx file was generated in the profiler output directory I had provided.

Now, which tool to use (on my Windows computer) to process this file and get a visual representation of my code’s performance?

After some Googling, I found KCachegrind for Windows (called QCachegrind, compiled by Lailin Chen). This seemed to be the best application available. And after downloading the ZIP-file and it’s contents to the Program Files directory, I executed kcachegrind.exe and opened the generated cachegrind file (I had to type in the exact name of the file, since it didn’t match the file filter in the File open dialog of KCachegrind).

When the file was processed, I selected the {main} function and clicked on Call Graph. Who would have guessed: it generated exactly the picture I had in mind!

Jul 8 11

Symfony forms convenience method: addPostValidator

by Matthias Noback

In your Symfony form, only one post validator can be set, by using $this->getValidatorSchema()->setPostvalidator(). But sometimes you extend a form and a post validator was already set in the parent class, and you don’t want to replace it with your own post validator, but instead, add your own validator to the validatorschema. I wrote a convenience method for this task. Add this method to your form class:

public function addPostValidator(sfValidatorBase $post_validator)
{
  if ($existing_post_validator = $this->getValidatorSchema()->getPostValidator())
  {
    $this->getValidatorSchema()->setPostValidator(new sfValidatorAnd(array($existing_post_validator, $post_validator)));
  }
  else
  {
    $this->getValidatorSchema()->setPostValidator($post_validator);
  }
}

Use this method for example in your form’s configure or setup method:

$post_validator = new sfValidatorCallback(array('callback' => array($this, 'postValidator'));

$this->addPostValidator($post_validator);
Jun 9 11

sfDoctrineActAsTaggablePlugin displays JavaScript array methods as tags

by Matthias Noback

I recently stumbled upon some strange behaviour in a Symfony 1.4 Apostrophe project. The built-in media browser uses sfDoctrineActAsTaggablePlugin. Whenever I added some new media item or edited an existing one, a list of strange tags were added to the list of tags, which appeared to be JavaScript array methods (see the screenshot).

Apparently, serveral of the “for-in” statement in the plugin’s JS file loop over array methods as if they were elements of the array. The problem is fixed by making use of the jQuery .each() method to loop over the array elements. You can download the fixed JS file here: pkTagahead.js.

Until the fix is added to the sfDoctrineActAsTaggablePlugin trunk, you may fix the problem in the following way:

  1. Remove the symlink /web/sfDoctrineActAsTaggablePlugin
  2. Create a directory /web/sfDoctrineActAsTaggablePlugin
  3. Create a directory /web/sfDoctrineActAsTaggablePlugin/js
  4. Copy the fixed pkTagahead.js (download link above) to this directory
Mar 17 11

Accessing the front-end routing from the back-end application

by Matthias Noback

As a follow-up on my previous post about accessing the front-end sfI18N object from the back-end application, I now provide you with a way to access the front-end routing, from another application, in my example the backend application.

First, add the method getRouting() to your backendConfiguration class:

class backendConfiguration extends sfApplicationConfiguration
{
  /**
   * Get the routing for the given application
   *
   * Optionally set context values, using the $context parameter
   *
   * @see sfWebRequest::getRequestContext()
   *
   * @param string $application
   * @param array $context
   *
   * @return sfRouting
   */
  public function getRouting($application, array $context = array())
  {
    $current_application = sfContext::getInstance()->getConfiguration()->getApplication();

    sfContext::switchTo($application);

    $factories = sfFactoryConfigHandler::getConfiguration(ProjectConfiguration::getActive()->getConfigPaths('config/factories.yml'));

    $class = $factories['routing']['class'];
    $params = $factories['routing']['param'];

    $params['context'] = array_merge(sfContext::getInstance()->getRequest()->getRequestContext(), $context);

    $routing = new $class($this->getEventDispatcher(), null, $params);

    sfContext::switchTo($current_application);

    return $routing;
  }
}

You should add lazy loading to this method, together with some “internal” caching of the generated routing class (by using a property of the backendConfiguration class). See my other post about generating another application’s sfI18n object for an example of this.

Once you have done this, you can access the routing by calling this method from any action, e.g.:

$routing = $this->getContext()->getConfiguration()->getRouting('frontend');
echo $routing->generate('news_detail', array('id' => 3, 'slug' => 'test'));

// this results in, for example: /news/3/test

From a backend application you may encounter some problems, because the generated route is based on the current request, so the script name is included. A problem also arise if you want to generate absolute URLs and you want to link to another site (or your back-end application is hosted on a subdomain), because the routing uses the current host name by default.

Luckely, the given method getRouting() provides a way to override these “contextual” options (see sfWebRequest::getRequestContext()):

$routing = $this->getContext()->getConfiguration()->getRouting('frontend', array(
  'prefix' => '/frontend_dev.php', // or '' in case you want no script name displayed
  'host' => 'www.symfony-project.org',
));

echo $routing->generate('news_detail', array('id' => 3, 'slug' => 'test'));

// this results in, for example: http://www.symfony-project.org/news/3/test
Mar 17 11

Accessing the front-end sfI18N object from the back-end application

by Matthias Noback

Sometimes you want to use the front-end application’s sfI18N object in the back-end application. Mainly because it has access to the front-end messages (they are placed in apps/frontend/i18n/[culture]/messages.xml). The most elegant way to accomplish this is by creating a method in your backendConfiguration class:

class backendConfiguration extends sfApplicationConfiguration
{
  /**
   * Get the I18N object for the given application and culture
   *
   * @param string $application
   * @param string $culture
   *
   * @return sfI18N
   */
  public function getI18N($application, $culture)
  {
    $current_application = sfContext::getInstance()->getConfiguration()->getApplication();

    sfContext::switchTo('frontend');

    $factories = sfFactoryConfigHandler::getConfiguration(ProjectConfiguration::getActive()->getConfigPaths('config/factories.yml'));
    $class  = $factories['i18n']['class'];

    $i18n = new $class(ProjectConfiguration::getActive(), null, $factories['i18n']['param']);
    $i18n->setCulture($culture);

    // load the message source (before switching back to the other application)
    $i18n->getMessageSource();

    sfContext::switchTo($current_application);

    return $i18n;
  }
}

You may of course add your own shortcut method for retrieving the sfI18N object for the frontend application, with the current culture. It is also important to make this method lazy loading and caching, so that the quite expensive code of loading the application configuration is not executed too often.

Mar 10 11

Looking back on Symfony Live 2011: part 2

by Sander Coolen

It was around eleven o’clock when we walked towards Boulevard Jourdan, which is part of a belt line road around the city centre and is parallel to the Périphérque, but with a smaller diameter. If we would follow the road east we would walk back to the RER station and the university, instead we went the opposite direction.

There were mostly large greyish buildings – probably from smog and exhaust fumes – typical for the outskirts of a major city. We passed a Lidl supermarket, which we already spotted on Google Maps back in the apartment, and checked for its opening and closing hours. There was a night shop across the street where we bought ourselves breakfast for the next morning. It had some pretty ridiculous prices, but we needed our coffee, jus-d’orange, baguettes and Nutella. I mean, you never really went to France if you haven’t had pain au chocolat. It’s like…it’s like bread with chocolate spread. It’s crazy. It’s luscious! And you always end up damaging you palate which you can then disinfect with some nice fresh orange juice. Yummy!

Up ahead the neon-lights of Le Corentin were trying to lure us inside. There were one or two bars more on the same block, but the first one was the most inviting. It looked quite gezellig. When we saw the price list it became a lot less gezellig. Almost 6 Euros for a (30cl) beer! Amsterdam isn’t inexpensive, but this was downright absurd. 25 cents per sip! The Dutch are known for being a bit cheap and nagging about prices, so we tried to live up to our names for the rest of the evening. Six Euros! Damn Paris, y u no cheap?!

After we finished our 50 buck round of drinks, one of my colleagues wanted to buy a second round. We thought he was seizuring, but he looked pretty healthy…and pretty serious. There is a Dutch saying: “Smaakt naar meer (tastes very moreish)”, but being screwed over is never really moreish. Luckily the waiter misunderstood our ‘another round’ hand gestures and brought the check. They are probably used to tourists getting the hell outta there after their first drink.
When we left the bar we had a quick glance over the neon sign and made a mental note: Le Corentin; ne jamais plus.

Mar 8 11

Looking back on Symfony Live 2011: part 1

by Sander Coolen

After a three hour Thalys-train ride we arrived at Paris Nord station. Another 20 minutes by RER brought us to a station just across the university complex in the south of Paris adjacent to the Montsouris park. From there we could walk to our apartment which was located uphill on the end of a cobblestone road with expensive looking houses and matching cars on their tiny driveways. The scaffolding around our building made us wonder if maybe we had booked for next year.

After we announced our arrival by a quick phone call, we were welcomed by the Romanian landlady Anna who led us to our suite. The funky smell of urine mixed with rotten edibles, in the hallway wasn’t very promising. Luckily inside the apartment it smelled a lot less fishy. Time to celebrate our arrival. Vive la France!

Unfortunately it was too late to get some beers at a supermarket, so we decided to drop our bags and go for a drink in a local bar. But first Anna gave us a tour around the apartment. Which, to my surprise, came close to the pictures we saw on the rental website. It had three large bedrooms with double beds and another two sleeping couches in the living area. Plenty of room for the seven of us. Minor shortcomings were the 40″ flat-screen TV which was replaced by a 30″ old-timer and the toilet which was slowly falling apart. It think it was transforming into a squat toilet. By the end of the trip we had to practically dive into the cistern to manually start the flushing mechanism. No need to wash your hands after that!

After we set up Wi-Fi on all of our ninety-nine lappadpods and changed the keyboard layout on the top-de-desque from god knows what to QWERTY, we were ready to hit the road. Or, as the French like to say: “‘It ze route!

Mar 4 11

Symfony Live 2011: Day 2

by ronald

Just before the final keynote speech, enjoying the sun in the garden at the back of the university building, I write my thoughts about the conference. Looking back two things jump to mind.

The first one is that Symfony2 looks very promising. It seems to solve a lot of personal programming annoyances I faced the last years programming with Symfony1. The main one being the the Form framework which is completely rewritten.

My second and more important thought is about the maturity of the Symfony community and the ideas behind it. Through my years of programming PHP (around 10 years now), the ‘script kiddie approach’ to programming in a large part of the PHP community always annoyed me. It did not keep pace with the growing expectations our clients have for their projects. With the arrival of frameworks like Symfony and Zend these days are finally behind us. Offering us the the professional tools and methodologies we so desperately need in our daily work delivering challenging and professional web applications. With that I conclude, go inside, to see what the final keynote of Fabien will add to this.

Edit: finally, also the new Symfony logo and website match these expectations ;-)

- Ronald

Thumbs up for Symfony2!!

————-

So close after the conference it’s hard to get a full overview of all things i have heard and what the consequences are for the future of Symfony(2) and the consequences for Driebit.

My head is full of Symfony2 components, bundles, technologies, Java side projects, subframeworks and other cool new things i’ve heard the past two days.
If one thing becomes clear after 2 days of Symfony Live, it is the fact that Symfony2 is built with best practices, great design patterns and separation of concerns in mind (and the lessons learned from symfony 1)
It is very losely coupled, and consists of a lot of standalone components glued together by the dependency injection container. This a great concept from an architectural and best practices point of view. What this means for me as a current symfony 1.4 user i don’t know yet.
Right now it looks like i need to learn a lot of different things, but i’m very eager, really!
Amongst others (not all new, but fairly new to me)
  • The user friendly and very promising Apostrophe Now CMS plugin (still only SF1)
  • The new form framework / annotations / validation feature without all the business rules and ORM couplings.
  • The Twig templating engine and its extensibility is like “Smarty on steroids” (good quote Sjors!)
  • Assetic asset management framework will give you an easy way to manage your assets, javascripts, stylesheets
  • All the new caching stuff that will make thing blazingly fast (HttpCache, Varnish etc) and using it in a SF1 application ()
  • GIT
  • The CMF framework project, which is still in a pretty early stage
One thing that really looked like a interesting way of incorporating testing features and user stories in a project is Behavior Driven Design (BDD) BDD defines a spec that not only programmers can learn, it’s also for readable non-technical people. There is a PHP framework called Behat.
The talk on Solr was pretty condensed for new users. A few months ago we did a Solr training so we felt more at ease with the load of information. Good to know there is a sfSolrPlugin available to play with Solr, that contains everythign you need to get started out of the box.
Nevertheless i’n absolutely amazed by all the beautiful things i have seen and heard.
Congratulations, thank you and respect for all the people who contributed to his in the last few years.
See you next year!
- Hidde
Driebit crew's Symfony Live 2011 badges

Our badges

“Back from an exhausting second day at the Cité Universitaire. Partly due to some lack of sleep, but mainly because it was packed with techical talk. We had an early kickoff today – 8:30am instead of 9:30. I attended “Symfony2: from the trenches” by Lukas Kahwe Smith, Jordi Bogginano and Jeremy Mikola. A sort of live walkthrough through some of the main Symfony2 components with an array of best practices and first-hand experiences. For me personally it filled a lot of gaps left after reading the Reloaded documentation and playing around with the sandbox. A positive start of the day.

Another interesting talk was the one by Fabien Potencier on HTTP Caching. Quite a bit of theory jammed into 50 minutes, but nonetheless – or probably therefore? -  a highly informative speech. It mainly covered two chapters of the HTTP 1.1 Bis Specification. A document that is a must read for us web developers, and for those who haven’t yet, should download it this week and read it back-to-back, to paraphrase Fabien.

A third personal highlight was the BDD (Behavior Driven Development) bit by Konstantin Kudryashov. BDD, an evolution of TDD, is a methodology combining both Unit and Acceptance Testing. He launched a Symfony2 Bundle recently, called Behat, that implements a small framework for this Agile development technique. Quite inspiring as Driebit has recently started with Scrum and is doing research into different testing techniques.”
- Sander