How to run your Symfony2 PHP app on Azure website

Windows AzureBestComparator is part of the DojoBoost accelerator in Paris and a Bizpark partner. We have the chance to have some partnerships with Microsoft and thus have some support and early access to some technology. Especially about Windows 8 and Azure.

Talking about Azure, they made tremendous upgrades to the platform during the year. They moved from a PAAS platform to a full layered cloud solution. From SAAS to IAAS you can do almost everything. Create a WordPress in a few clicks, create a VM, configure a VPN, create a SQL server, create a mobile service that interface an autogenerated backend storage with your iPhone/Android/Windows phones, scale your services by moving a slider…
Being at the Azure Open Source Summit really amazed me about all the possibilities that are offered to developers and how fast new features comes to the portal. One of those which interested me the most is the possibility to run a PHP website on Azure using the Web Site feature.

About PHP and Azure

PHPYou currently have two main options to run PHP on azure.

First you can simply create a VM using Azure Virtual Machine, after choosing an OS (Windows Server, CentOS, Suse, Ubuntu…) you just connect to your server and configure everything you need. You can change the size of you VM, it goes up to 8 cores and 15GB of RAM. I am running it in production for a few mounts now, and it is pretty stable and reliable. Nevertheless there are some drawbacks. You have to maintain your environment (which is not my job) and it has some limitations in terms of scalability (if you want more power, you will need to maintain another VM and start configuring load balancing and synchronization…). This is pure IAAS.

The other option I recently explored is using Azure website. You simply ask for a computation service which uses a code synchronized via git. It takes care about all the environment maintenance for you and just runs your code. Moreover, you can leverage some nice features such as the possibility to increase the size of the underlying instance (up to 4 cores and 7GB of RAM), but also increase the number of instances (up to 20) seamlessly. Azure takes care of the rest for you. This is more PAAS oriented and let you concentrate on developing your app.

Let’s start a first PHP website:

  1. First of all go to your azure portal
  2. Create a new website using the custom wizard
  3. Select the name of your website, the region, a database (or not) and check the “publish from source control” option
    step2
  4. Choose “git” and “local git repository” as source control setup
    step3
  5. In a third step select your credential, they will be required for git synchronization and ftp login (if you want to)
  6. Now, open the deployments panel in the newly created website you will find there the git url
    step4
  7. On your local machine, simply clone the repository (or set a remote): git clone https://michel@blog-test.scm.azurewebsites.net/blog-test.git
  8. Put your PHP code in the cloned repository, commit, and push to azure
  9. When pushing to azure, it will automatically publish the newly updated code to the website, you can visualize it directly by connecting to the url of the website displayed in the website dashboard

At this point you can upload PHP code to Azure and run it. Here is what you might want to know:

  • You can switch PHP version (5.3 and 5.4) in the configure tab
  • You can scale the size and the number of the instances in the scale tab
  • You can map your domain name using the “manage domain” option available in the bottom bar if you are in “shared” or “reserved” mode (available in the scale tab)
  • If you don’t want to deploy from a local git repo, you can using github, codeplex or bitbuket. It is configurable from the wizard in step 4.
  • You can set environment variables in the configure tab
  • You can choose which branch of your git to deploy in the configure tab
  • You can access the server via ftp using the credential given in step 5 and the ftp configuration in the dashboard
  • You can override the php.ini by giving a .user.ini at the root of your repo

What about Symfony2 websites?

Symfony2 LogoRunning a Symfony2 website is doable but it will require some more work. You will have two main issues to fix:

  1. Activate url rewriting to web/app.php, and reroute web requests to the web directory
  2. Find a way to use the composer and the console

The first issue can be tackled simply by adding a Web.Config file at the root of you repo. It works just like .htaccess for apache but for IIS. Here is the content:

<?xml version="1.0" encoding="UTF-8"?>
<configuration>
    <system.webServer>
        <rewrite>
            <rules>
                <rule name="web directory">
                    <match url=".*" ignoreCase="false" />
                    <action type="Rewrite" url="web/{R:0}" appendQueryString="true" />
                </rule>
                <rule name="app_php handling" stopProcessing="true">
                    <match url="^(.*)$" ignoreCase="false" />
                    <conditions logicalGrouping="MatchAll">
                        <add input="{REQUEST_FILENAME}" matchType="IsFile" ignoreCase="false" negate="true" />
                    </conditions>
                    <action type="Rewrite" url="/web/app.php" appendQueryString="true" />
                </rule>
            </rules>
        </rewrite>
    </system.webServer>
</configuration>

In the Web.Config file we define two rules. The first one reroutes every request to the web directory, and the second one routes the requests to the web/app.php script when there is no physical file requested.

I did not yet tackled the second issue (ie. composer and console use). What I know is that there is no command line access to Azure website but it seems like you can use the exec PHP function from PHP scripts. So everything seems doable with some web interface that simulates command line using PHP functions. I will edit this post as soon as I find a better solution.

What if I want to add some extensions/tweak to PHP runtime?

You may notice that Symfony recommends the use of the intl extension for PHP which is used for internationalization of the validation component (and also in some BCC bundles). You might also need a specific setup of PHP such as a specific version, a configuration which cannot be overridden in the .user.ini file or another extension.

Don’t worry, you can give to Azure you own PHP runtime:

  1. Go to http://windows.php.net/download/ and get the version of PHP you want (which has to be “VC9 x86 Non Thread Safe”)
  2. Unzip it to a directory in your repo, in my case in a ./bin directory
  3. Configure your php.ini file in bin/php.ini
  4. Remove the extensions you don’t want in bin/ext/*
  5. Add, commit and push the files (which might take some time considering the size of your php runtime)
  6. When git is synchronized, go the configure tab on azure
  7. At the bottom of the section, add a handler mapping configuration. The extension is *.php and the script processor path is D:\home\site\wwwroot\bin\php-cgi.exe (because D:\home\site\wwwroot\ is the root of the website and my PHP runtime is in the bin directory)
    step5

Everything is set and you website now runs on your own PHP runtime.

Wrap up

Despite Azure is very young, it offers a lot of possibilities in terms or configuration. I hope this post will help you understand better how it works and how to setup your favorite PHP environment while leveraging all the nice features of Azure.

Doctrine Logo

Doctrine2 ninja with the HIDDEN keyword

I recently came to find a nice hidden feature of Doctrine2, the well named HIDDEN keyword.
I first needed to find the feature because I wanted to use functions in an order by clause.

The problem

Let’s say you want to get your user ordered by sum of comments and likes. You will write this kind of DQL:

SELECT u
FROM BCCModelBundle:User u
ORDER BY u.commentNumber + u.likeNumber

Sadly, for interoperability reasons, such a statement is not possible using doctrine2. You cannot have an arithmetic expression in the ORDER BY clause. This goes also with the GROUP BY

The solution: the HIDDEN keyword

Hopefully, you can use the HIDDEN keyword. This idea is to declare a new field in the SELECT clause and mark it hidden to avoid the ORM fetching it:

SELECT
	u,
	u.commentNumber + u.likeNumber AS HIDDEN score
FROM BCCModelBundle:User u
ORDER BY score

Now, you have a score field which is compatible with the ORDER BY clause. I am sure you will find it very useful, especially when you will starting to have heavy DQL with complex ORDER BY clause.

EDIT: Please note that this feature is available on Doctrine 2.2+.

Symfony2 Logo

Welcome the BCCCronManagerBundle, the Symfony2 bundle that helps you managing your crons

One thing I don’t like to do when maintaining a website, is having to pull out ssh on a daily basis in order to check that everything is running fine. A basic use case is scheduling and watching crons.

So I recently came out with the idea of building a web interface wrapping the use of the crontab command with some tools for watching associated log files.

And thus, the BCCCronManagerBundle was born.

A quick presentation

The BCCCronManagerBundle can already do some nice things:

  • display the cron entries of the cron table, parsing time expression, command, output file, error file and comment
  • guess the last execution time and status
  • display log files
  • add, edit and remove cron entries

The bundle is localized in english and french. The forms also include some shortcuts t easily build common time expression, launch a symfony command or log in the symfony log directory.

The cron list

The cron list

The cron form

The cron form

A cron log file

A cron log file


How it works

Actually, the architecture is quite simple. Everything relies on two classes: CronManager and Cron.

The CronManager launches the [cci]crontab -l[/cci] command in constructor, then extracting each lines in order to build a collection of Cron instance. It has get, add and remove methods in order to access the Cron collection. A raw method build up the cron table string based on the Cron collection and a write method puts it into a temporary file before launching the [cci]crontab $file[/cci] command.

The Cron class is instantiated using the parse static method. Its job is to parse a cron line from the cron table and extract the time expression, command, output, error output and comment (if defined). Based on the output files it can guess if the cron has already been runned (one of the output files is present) and if it was successful or not (the error file is empty). A getExpression method can build the time expression and the _toString is overriden in order to give the cron representation for the cron table.

The interface is quite neat, thanks to Sam. He helped me implementing the twitter bootstrap which is very powerfull and elegant. I also decided to make use of the jQuery plugin that is quite impressive and can easily replace jQueryUI on some points.

Wrap up

You can download and install the bundle on the github : https://github.com/michelsalib/BCCCronManagerBundle.
I also welcome contributions for any improvement, such as a better cron table parsing, more options for cron definition (such as log files), better support of multi platforms, or translations.

Symfony2 Logo

BCCExtraToolsBundle for Symfony2 now includes new features

The purpose of this blog post is to review the last features that have been included into the BCCExtraToolsBundle.
As you may know, its current main feature is a command that extract translation string from your template and dump them into your translation files. It has been so popular that the code has been adapted and merged it into the code Framework a few months ago with the help of the community.
Sadly, I will eventually remove this functionality from the bundle when the 2.1 version will come out. Hopefully, I recently add new cool stuffs into the Bundle recently that you may find useful.

A date parser

You may know that the Bundle currently includes a date formatter that provides you a nice way to localize your dates directly with a twig filter.
I reviewed the code recently to provide a way to make the operation working the other way. You can now do such things :

[cc_php]
get(‘bcc_extra_tools.date_formatter’);

// obtain a datetime instance for a normally formated string
$date = $dateFormatter->parse(‘November 1, 2011′);

// obtain a datetime instance using a defined locale
$date = $dateFormatter->parse(‘1 Novembre 2011, 20;14’, ‘fr’);

// obtains a datetime instance with a uncommon string
$date = $dateFormatter->parse(‘Nov. 2011);

[/cc_php]

Basically, the code is trying every parsing it can using the formats available for the formatter (more information here http://www.michelsalib.com/2011/07/a-twig-extension-that-translates-countries-and-dates/) and more so that it can parse almost anything.
Of course it can be very handy when you consume some weird API using nonstandard datetime formatting.

A unit converter

About consuming API. I can be very annoying to find some values in a unit don’t want to use. The unit formatter is here to help you:

[cc_php]

get(‘bcc_extra_tools.unit_converter’);

// transform a value knowing the source and destination units
echo $unitConverter->convert(1000, ‘m’, ‘km’); // echoes : 1

// transform a value knowing only the destination units
echo $unitConverter->guessConvert(’1h’, ‘m’); // echoes : 60

[/cc_php]

To do such work, your value will go through different phases::
- A chain unit converter will try to convert using its DI registered unit converters
- A ratio unit converter which converts units that are strictly proportional will take care of most your conversion
- The ratio unit converter supports different kind of units registered using DI, such as length, weight, speed, time… those are called ratio unit providers
- Ratio units providers defines units and ratios related to a specific unit kind. It includes also the locale where the unit is applicable and the prefixes that can be associated to the unit. For instance, the computer capacity unit kind will define the octet, the bit and the byte with their corresponding conversion ratio and the applicable prefixes (k, M, G…).

With such a structure, the converter insure you that any prefix is taken into account, that the conversion is done between coherent units (it won’t try to convert time into money… sadly), and it also takes into account your current locale (the ‘metre’ is the french unit for the ‘meter’).

I’ll try to add more units and documentation in the coming posts.

Wrap up

The BCCExtraToolsBundle continues to provide useful features to the developers. Get the code of the datetime parser and the unit converter on the BCCExtraToolsBundle github : https://github.com/michelsalib/BCCExtraToolsBundle. Don’t hesitate to report issues, feedback and improve the code :)

Symfony2 Logo

Introduce the BCCAutoMapperBundle for Symfony2

One of my favorite tools with my .NET developments is definitely AutoMapper. It allows to easily mapping objects to other objects by generating default maps for graph of objects base on the name of the different members.

I found it quite a shame that such a tool did not exist on the PHP platform. So I started a new Symfony2 bundle to palliate this lack.

How the AutoMapperBundle works

You can find it here: https://github.com/michelsalib/BCCAutoMapperBundle.

As a quick example here to show you how you can map objects together. Here is your model:

[cc_php]
name = $name;
$this->description = $description;
$this->author = new SourceAuthor($author);
}

public getName() {
return $this->name;
}

public getDescription() {
return $this->description;
}

public getAuthor() {
return $this->author;
}
}

class SourceAuthor {
private $name;

public __construct($name) {
$this->name = $name;
}

public getName() {
return $this->name;
}
}

class DestinationPost {
private $title;
private $description;
private $author;

public getTitle() {
return $this->title;
}

public setTitle($title) {
$this->title = title;
}

public getDescription() {
return $this->description;
}

public setDescription($description) {
$this->description = description;
}

public getAuthor() {
return $this->author;
}

public setAuthor($author) {
$this->author = author;
}
}
[/cc_php]

Then, in you application:

[cc_php]
get(‘bcc_auto_mapper.mapper’);
// create default map and route members
$mapper->createMap(‘MySourcePost’, ‘MyDestinationPost’)
->route(‘title’, ‘name’)
->route(‘author’, ‘author.name’);

// create objects
$source = new SourcePost(‘AutoMapper Bundle’, ‘A great bundle’, ‘Michel’);

// map
$destination = $mapper->map($source, $new DestinationPost());

echo $destination->getTitle(); // outputs ‘AutoMapper Bundle’
echo $destination->getDescription(); // outputs ‘A great bundle’
echo $destination->getAuthor(); // outputs ‘Michel’
[/cc_php]

Read the doc on the github to find more explanation and more functionalities: https://github.com/michelsalib/BCCAutoMapperBundle.

This is a very light implementation and some cases are not covered yet (such as dynamic graph creation). Please, don’t hesitate to fork me and provide feedback.

Symfony2 Logo

A twig extension that translates countries and dates

For today’s tutorial, we will see how to create a Twig extension that provides two filters that localize countries and dates.

What is wrong
In Symfony2, you might run into this issue. For instance, countries that are saved by form using the CountryType are stored using a two letter code. For instance you can have US for “United States”, UK for “United Kingdom”… The problem is that you cannot use it directly; you need a read string representation. Moreover, this string representation varies depending on the current locale.
Also you will have exactly the same trouble with dates, which can be “January 1rst” in English and “1er Janvier” in French.

What we need
The easiest way to handle this kind of translation is to use a twig filter. At the end we want this syntax:
- [cci]{{ user.coutnry | country }}[/cci]
- [cci]{{ user.birthday | localeDate }}[/cci]

Note that such a translation cannot be done easily without the use of the apache2 intl module. You have to install it on your server before going any further : http://www.php.net/manual/en/book.intl.php.

Create a twig extension
Adding filters into Symfony2 is quite simple. You need to create a new class that override the [cci]Twig_Extension[/cci] class.

Then we can override the [cci]getFilters[/cci] and the [cci]getName[/cci] functions.
[cc_php]
new Twig_Filter_Function(
‘MyVendorMyBundleTwigTwigExtension::countryFilter’
),
‘localeDate’ => new Twig_Filter_Function(
‘MyVendorMyBundleTwigTwigExtension::localeDateFilter’
),
);
}

public function getName()
{
return ‘myExtensionName’;
}
}
[/cc_php]

Note that at this moment the country and the localeDate are defined. When we will use them from a template they will call the defined static functions.

The country filter
The country function will use the list of countries already used by the Symfony2 form component. It is the [cci]SymfonyComponentLocaleLocale[/cci] class:
[cc_php]
<?php
namespace MyVendorMyBundle Twig;

use SymfonyComponentLocaleLocale;

class TwigExtension extends Twig_Extension {

//…

public static function countryFilter($country)
{
$countries = Locale::getDisplayCountries(
Locale::getDefault()
);

return $countries[$country];
}
}
[/cc_php]

The code is pretty straightforward. Just note that to obtain the application locale we use the [cci] Locale::getDefault()[/cci] function, this [cci]Locale[/cci] class is provided by the intl extension. Also when Twig calls the filter, it always sets as first parameter the filtered value.

The localeDate filter
The filter for the date is a little more complicate:
[cc_php]
IntlDateFormatter::NONE,
‘short’ => IntlDateFormatter::SHORT,
‘medium’ => IntlDateFormatter::MEDIUM,
‘long’ => IntlDateFormatter::LONG,
‘full’ => IntlDateFormatter::FULL,
);
$dateFormater = IntlDateFormatter::create(
Locale::getDefault(),
$values[$dateType],
$values[$timeType]
);

return $dateFormater->format($date);
}
}
[/cc_php]

First of all we added two more optional parameters. They will serve to override the kind of rendering we want for the filtered date. We can use them like this :
– [cci]{{ user.createdAt | localeDate(‘long’,’medium’) }}[/cci] for a long date and a medium time representation

Then we create a date formatter which is an instance of [cci]IntlDateFormatter[/cci] parameterized with our format parameters. I used an associative array to translate string parameters to the supported contants.

Then we can simply format the date and return it using the [cci]format[/cci] function.

Activate the twig extension
In order to activate the twig extension, you need to register it as a service to the container. In order for the container to know it is a twig extension, you need to add the [cci]twig.extension [/cci] tag.

Just add to your [cci]config.yml[/cci] file:
[cc]
services:
bcc.twig.extension:
class: MyVendorMyBundleTwigTwigExtension
tags:
– { name: twig.extension }
[/cc]

Wrap up
We build a nice powerful twig extension that provides two filters that helps localize countries and dates.

You simply add the extension to your project by checking out the BCCExtraToolsBundle : https://github.com/michelsalib/BCCExtraToolsBundle.

Symfony2 Logo

A symfony1.4 to Symfony2 migration: Why you should learn Symfony2

Since a few months all the PHP developer’s community is quite in turmoil about everything that’s going on. PHP 5.3 is becoming very standard, Zend is in heavy development for his new version and Symfony2 is on the point to release his final version.

What’s happening?

Before going further, I must make a quick overview of what’s happening in the world of PHP developers.
The news coming frameworks are reaching a new step in professionalization of PHP developments. And this one is very huge! The provision of modern design patterns such as SOC (separation of concerns), DI (Dependency Injection) or Annotations (even if it not really a design pattern) pulled the Frameworks to new high quality standards. Note that Java and Microsoft worlds joined this state years ago, PHP is just catching up.

And this catching up is really fast! Essentially thanks to GitHub which allows the lead development team to be easily helped by thousands of voluntary developers all around the world. Really, GitHub community amazes me every day.

Consequently, new generation PHP Frameworks relegate past frameworks to an old way of developing. “Yea my Framework does MVC! So don’t I have some kind of a modern architecture?” Of course not! I am quite bored of this excuse which leads to poor development quality. Take for example the Symfony1.4 Framework. It uses obviously MVC, but outside of the views and controllers all the rest stays messy.

What I realized last months is that PHP development became a language where you can really develop an expertise based on framework but also on architecture and best practices. And it feels right. You cannot tell anymore that you master PHP just because you understand the language and a Framework.

Fact: PHP is becoming a very professional and valuable technology, just next to Java and .NET.

PHP and some"modern" Frameworks

PHP and some"modern" Frameworks

Learn a new Framework

What I did in the beginning of 2011 is the migration a full featured website from symfony1.4 to Symfony2.

First of all, I must say that symfony1.4 is a tremendous Framework. It is reliable and well-conceived. I learned a lot using it. If you like it and are using it on current projects, you should definitely keep it.
But when I saw Symfony2 at the end of 2010, I couldn’t help myself but to be thrilled about it. Symfony1.4 is nice, but Symfony2 is so much better!

You have several advantages to learn and use Symfony2. You will learn and use new philosophies and best practices that are very valuable. Functionalities and performances are better. Team development is enforced with a much decoupled framework. And you can easily leverage the GitHub community which tests and improve the Framework every day or provided Bundles for every need.

You should learn Symfony2, but the road is not easy.

Symfony1.4 to Symfony2

Yes, the architecture is completely different. And despite the fact that the name stays the same, you will have to recode everything again. This is why we advise to keep current symfony1.4 project the way they are.

Of course, you will get some kind of a step by step tutorial to migrate the code. But at the end you will recode everything.

The general architecture

The main difference is that this time you won’t code into the framework (remember the model directory for example). You will have to create a Bundle.
A Bundle is some kind of a library that has the ability to be plugged into Symfony2. Bundles are very independent one from another and are at the core of your application. Note that Symfony2 is itself built on Bundles. Also, old plugins are now Bundles.

A Bundle could be your model, your frontend, a web service, a template engine, an ORM, a search engine, an integration of TinyMCE… so Bundle is a very large notion in the Symfony2 framework. The main interest it that they can be very easily plugged, updated and configured.

It took me several months to fully understand what the implications of using Bundles are. But once you’ll get it, you won’t want to leave it.
Also Symfony2 relies on the concept of dependency injection. It is very important to understand why it is build this way, what the container is and what it implies. When you’ll know how it works, the Framework will become very easier to understand.

Doctrine2

Doctrine2 works differently.

The first thing you’ll notice is that Doctrine does not rely on code generation. Now you will have to code your objects yourself. Hopefully the command can help you to build your first objects, but you should rapidly code your files directly.

Consequently, your objects are not using any base class. They are lighter but they don’t have any access to the ORM, and should not contain the saving logic anymore.
You might also use annotation, which are very powerful and have the merit to explicitly set relationships.
What I like with Doctrine2 is that your model is now very light and explicit. You won’t have the WTF effect any more when a relation or column is not loaded/stored correctly because of a wrong “schema.yml” file.

The Controllers

Controllers may contain the same kind of logic; the way they work is different. Now you have to consume services. And so you will learn the notion of services and begin to use one of the core items of the Symfony2 architecture: the container. No more static classes, you will rely on real instances that are parameterized via all the dependency injection and services logic.

Really, services, dependency injection and the container are very nice things. They allow your code to be more decoupled and more robust.

The views

Twig is one of the most powerful stuffs in Symfony2. You may don’t want to use it, but I strongly encourage you to do so.

The syntax is less verbose, and you can have a lot of nice functionalities. Auto escaping, easy access to variables, template inheritance, easy test structures (which can be boring in php, such as testing the existence of a value, or test even/odd occurrences in a loop), filters (truncate, text replacement, capitalization)… and so on.

Twig is a language dedicated to designers, so that you won’t have to teach them PHP.

Also Twig will impose you to have only view logic in your view. And that is great! You designer can concentrate on creating a nice interface without messing with your business logic.

The routing

Really, the routing looks like to be the least changed component. It became a little simpler than before, can be used with annotations and has some nice new functionalities such as the param converter.

Forms

Forms completely changed. It is a brand new form Framework which works like a mix of MVVM and Converter design patterns (very common in .NET). You will have to go through all your forms in terms of composition, validation, and process.

As far as I can see, the new Form framework is not so easy to master. It is also one of the last stable components in Symfony2. As long as I can see, when it comes to functionalities, there is no major improvement.

But when you get how to use them, they become very powerful and fast to use. Especially thanks to the validation that can use annotations, and the very clean process of form construction.

Security

The security component is certainly the hardest to master. The first time I had to use it, it was very painful. You will have to understand many new concepts, such as the provider, the firewalls, the encoders…
But you will have a very powerful tool to really control every aspect of your web application security and authorization mechanisms.

I18n

The translation of your views is very clean and perfectly integrated in the twig syntax. The forms won’t get you any trouble.

But there is no out of the box process for the translation of your doctrine object. You will have to install the doctrine extensions, which are kind of official and not very hard plug, in order to support this feature.

On the bright side you can now have your translations in xliff files, but also php, yaml, and more.

Extending the framework

This last point is certainly one of the most important. Because complete parts of the framework are Bundles, it is very easy to build new bundle and makes them do whatever you want! Also it allows you to override very easily the way the framework behaves.

Because Bundles are kind of standalone, you can share them and plug them very easily. You can already find very popular bundles with very powerful stuffs in it. I am thinking about the KnpUserBundle, the SonataAdminBundle, the StofExtensionBundle or the ImagineBundle.

What will happen?

The first thing you might want to do is to download the Symfony2 package, configure your web server, and see what comes out. But it is not so easy. You first have to choose a distribution, get the “vendors”, maybe by using git…

Just after that you will go through the doc, and see that you have so many things to read, with some kind of an arbitrary order. Also they are a lot of cookbooks that contains so many features to discover. You will just want to know everything in order to make the right decisions. But you will still want to code.

You will be overwhelmed by the Framework and feel kind of lost. Almost I did.

You will “loose” time reading doc, learning new ways of doing stuffs that were working perfectly on your last framework. You will be stuck again common issues, and some other tricky functionalities will work very smoothly. At last you will learn to watch Github regularly to follow the development of some bundles, read the doc hosted there, and so on. You might not want to do that at the beginning (it is not what you came for)… but you will do.

The truth is that your first Bundle (application) will be crappy. Sure it will work, but you’ll be frustrated to miss some new features along the way. So you might refactor several times before getting all the potential of Symfony2.

During my migration I did not just recode everything. I had to refactor my forms two times, my security and the import of the assets one time. My controllers were permanently recoded to follow these changes. And so on.

The same thing happened to me when I discovered Symfony1.4. But, as always, you will feel some kind of betrayed by the Framework. You will have to overcome many frustrations and disappointments. And it might last for some months, but you had the strength to learn symfony1.4 so the learning of Symfony2 will be incredibly fast!

After all you will be a kid again, playing with big toys. You will surely miss your old ones, miss some functionality. But when you will know how to use them, they will become very pleasant tools.

The change curve

The change curve

What you’ll miss

Symfony2 is not so extraordinarily good. It is still very young, and it is thus missing some functionalities that symfony1.4 has.

You can forget about the admin generator for the moment. Symfony2 should get one, but not now. You can still compensate by using the SonataAdminBundle or the WhiteOctoberAdminBundle.

The Framework is too much flexible at first. You can do almost any file architecture. You can use xml, yaml, php or annotation as configuration. It seems nice, but sometimes it is kind of confusing to have a permissive Framework, especially after using symfony1.4.

No Jobeet. No Jobeet. No Jobeet. Sadly it is not coming soon. I have seen some projects to migrate the Jobeet project to Symfony2, but it is not very conclusive yet.

The magic. You will have to code your assessors yourself (or use a helper command), you will have to explicitly route your controllers and templates…

What you’ll like

The performance! Nothing more to say.

The new debug toolbar which is more powerful.

The documentation. It has no Jobeet, but it becomes more complete every day and you won’t have a specific documentation for the 1.0 to 1.4/Doctrine/Propel versions of the Framework. It wasn’t the case a month ago, but now the Symlfony2 documentation is more complete that the Symfony1.4 one. Thanks to the documentation team and the Github contributors that do a tremendous work.

Everything is explicit. “No more magic” can look like a nice easy thing to say, but is a very apparent and useful. Now the templates are called because you wrote it, your assessors are explicitly written, logic is not hidden into base classes that belong or are generated by the Framework, your configuration is loaded because you referenced it… No more “finger crossed” effect.

The community. The Symfony community has never been so active. You have lot developers ready to help you whatever your problem is. Moreover your will find a lot of nice Bundles on Github provided by the community.

You will learn a lot! You will use valuable practices and standards. You will build powerful, robust and nice web applications. And finally you will become a better developer than ever.

Some extras

Of course Symfony2 comes with some killers features. Let’s talk about some of these.

The management of assets is incredibly neat. The pre-packaged AsseticBundle can handle in a very elegant way all your assets. They can be images, css or js. But it can also compile on the fly coffee script, sass, lesscss or more, minifies tem, combine them and cache them!

You can do more by using the ImagineBundle that will handle your images. It will generate thumbnails, apply filters or watermark on the fly depending on what you ask in your templates. And it is cached.

Yes, my designer is very happy!

The cache has never been so powerful. Symfony2 uses the http headers (what a weird nice idea) coupled with a reversed proxy to reduce drastically what your application need to compute. Also it integrates in an almost transparent way the handling of ESI cache (if you don’t know it, you should at least look at this: http://en.wikipedia.org/wiki/Edge_Side_Includes).

Functional and unit tests are completely integrated into phpunit so that you can leverage a true PHP unit test framework.

Because everything is decoupled in bundles and only accessed via the container, your classes are loaded just when you use them. And it results in a very lightweight Framework compared to what symfony1.4 was.

The management of updates. It was not so easy at the beginning, but the core development team came with a script that can update your entire framework and dependency bundle just by reading a “deps.ini” file. Because your code is in a completely isolated Bundle you won’t have to do more than update the “deps.ini” file and run a simple command (which wasn’t really the case with symfony1.4 where your code were placed everywhere in the Framework).

What did I get?

I already told some of the reason why you should learn Symfony2. But there is more to say.

Again, Symfony2 will teach you many new nice things. You will learn. You will be a better developer than ever. And you will be more valuable.

Also your application will become much more powerful, fast and reliable. And that not nothing! I never felt so confident about my development and my websites.

At last you might enjoy it! Many new features of Symfony2 allow you to do so powerful stuffs without all the boring code. I am thinking about ESI, Assets management, Twig, Annotations, Bundles…

At the beginning you will hate learning Symfony2, but at last you won’t regret it.

Symfony2 Logo

Comment déployer une application symfony2 sur OVH

Exceptionally, this article is in French. I’ll talk about how to deploy a symfony2 application on an OVH server, which is a french webhost.

J’ai récemment déployé mon nouveau projet symfony2 sur mon serveur mutualisé OVH. Et c’est après quelques petites astuces que j’ai pu faire marcher tout cela sans heurt.

La première chose à savoir sur un serveur OVH, c’est comment changer la version de php. En effet la version par défaut est la 4.4.9 au moment où j’écris ces lignes, alors que symfony 2 requiert au mois la version 5.3.2.

Pour avoir la dernière version de php en ligne de commande : [cci]php.TEST.5[/cci]

Et pour activer la dernière version de PHP pour apache, mettez en tête du .htaccess :

[cc]
SetEnv REGISTER_GLOBALS 0
SetEnv MAGIC_QUOTES 0
SetEnv ZEND_OPTIMIZER 1
SetEnv PHP_VER 5_TEST
[/cc]

Comme vous pouvez le voir, j’ai rajouté quelques lignes pour avoir une configuration plus propre.

Ensuite, si comme moi vous développez en environnement Windows, vous allez avoir des erreurs signifiant que symfony n’arrive pas à charger certaines classes. Cela vient probablement du fait que vous avez oublié de respecter la case dans le nommage de vos répertoire ou bien dans le fichier [cci]/app/autoload.php[/cci].

Finalement, lors de l’utilisation de la commande [cci]assets :install web[/cci] pour le déploiement de vos ressources (images, swf…), la commande risque de vous signifier que le répertoire [cci]web[/cci] n’existe pas. Pour cela vous devez pointer vers le répertoire avec un chemin relatif au répertoire [cci]/app/[/cci]. Ce qui nous donne : [cci]assets :install ../web[/cci].

Et voilà, normalement tout fonctionne. En cas de soucis, n’oubliez pas de vérifier la configuration de la connexion à votre base de données dans le fichier [cci]/app/config/parameters.ini[/cci] et d’effacer le répertoire [cci]/app/cache/prod/[/cci].

Note : A propos de php, il est toujours possible d’avoir la liste des versions disponibles en faisant [cci]ls -l /usr/local/bin/php*[/cci] depuis la ligne de commande.

EDIT: la dernière note est devenue obsolète. De plus php.TEST.5 n’est plus utilisable, on peut maintenant utiliser php.ORIG.5.3.2.

Symfony2 Logo

Symfony2 : More about the ExtraToolsBundle

Following some of my previous posts A translation message extractor command and Create your own constraint validator in symfony2 : A Doctrine unique validator, these two handful functionalities are available on Github in the ExtraToolBundle.

Please, fork me ;)

Also, both functionalities have been strongly improved since I have blogged about them.

The Doctrine UniqueValidator, is now much more configurable and have been updated to support the new namespace annotation injection. And, thanks to Matt Agar the trans:udpate command is now much more robust and supports export to xliff and php translation files. He did a very nice job and it was very nice to have another developer to challenge and contribute to my implementation.

You can find the full details of the new tools on the ExtraToolsBundle’s github.

Symfony2 Logo

Symfony2: A translation message extractor command

One of the very painful taks you may face using symfony2 is the extration of all you translation message from your twig templates. This is much more annoying knowing that symfony1.4 did the job for you with a simple command, which does not exist in symfony2.

Today I will give give you a command for symfony2 that checks all your twig messages, combine them with your already existing messages in your yaml translations files and save the new ones. It is a recent work for me and it just works with twig/yml files.

The Command
I embedded it in a Bundle on github: https://github.com/michelsalib/ExtraToolsBundle.

You just need to get it, register the namespace and the bundle.

The name of the command is [cci]bcc:trans:update locale bundleName[/cci], where the [cci]locale[/cci] is the targeted locale (en, fr, es…) and the [cci]bundleName[/cci] is the name of the targeted bundle. You have several options:
- –dump-messages to display your final messages
- –force to update/write your translation files, it also perform a backup of the old ones
- –prefix=”…” if you want to change the prefix use for your new messages, by default [cci]__ [/cci] is used

Some example:
- To extract the messages of your bundle and display them in the console:
[cci]bcc:trans:update –dump-messages fr MyBundle[/cci]

- You can save them:
[cci]bcc:trans:update –force fr MyBundle[/cci]

- In another language:
[cci]bcc:trans:update –force en MyBundle[/cci]

- Or if you want to chaneg the prefix used to generate the new messages:
[cci]bcc:trans:update –force –prefix=’myprefix’ en MyBundle[/cci]

Behind the scene
The trick behind the code is how to properly crawl your twig templates.

First to get them:
[cc lang="php"]
// get bundle directory
$foundBundle = $this->getApplication()->getKernel()->getBundle(‘MyBundle’);
// get twig templates
$finder = new Finder();
$files = $finder->files()->name(‘*.html.twig’)->in($foundBundle->getPath() . ‘/Resources/views/’);
// iterate over the files
foreach ($files as $file) {
$path = $file->getPathname();
// parse the files
}
[/cc]

Here you just need to use the kernel to retrieve the bundle data from a simple bundle name. When you have the bundle path, you can use the finder to get all the file ending by [cci].html.twig[/cci] in the relative [cci]/Resources/views/[/cci] directory.

You can now parse the twig files:
[cc lang="php"]
$tree = $twig->parse($twig->tokenize(file_get_contents($path)));
[/cc]

Then you get a tree composed of [cci]Twig_Node[/cci]. The rest is just an algorithmic problem using recursion and type checking to find [cci]SymfonyBridgeTwigNodeTransNode[/cci] (for [cci]{% trans %}…{% end trans %} syntax[/cci]) and [cci]Twig_Node_Print[/cci] that contains trans filter (for [cci]{{ … | trans }}[/cci] syntax).

When you finally have all your messages, you might want to save them into yaml. For that you have two very simple static functions:
[cc lang="php"]
// get a yaml file into a php array
$array = SymfonyComponentYamlYaml::load($path);
// transform an array into a yaml string
$yml = SymfonyComponentYamlYaml::dump($array);
[/cc]

Wrap up
I hope this command will help you building better symfony2 app, by automatizing some work. Don’t hesitate to report me bugs, suggestions or to fork me on github!