How to force symfony colors on windows with PuttyCyg?
Those of you who’re developing with symfony under windows will have noticed that, when running tasks in the command prompt, no colors are used. This is because the windows command prompt isn’t compatible with the color notation.
Most of you also have cygwin installed (shame on you if you didn’t :p). But even if you run the tasks through “PuttyCyg”, which is fully compatible with the color notation, you will not benefit from the colors.
Why?
Quartz: test a cron expression

quartz logo
import java.text.ParseException;
import java.util.Date;
import org.quartz.CronExpression;
public class CronTester {
public static void main(String[] args) throws ParseException {
final String expression = "0 0 * * * ?";
final CronExpression cronExpression = new CronExpression(expression);
final Date nextValidDate1 = cronExpression.getNextValidTimeAfter(new Date());
final Date nextValidDate2 = cronExpression.getNextValidTimeAfter(nextValidDate1);
System.out.println(nextValidDate1);
System.out.println(nextValidDate2);
}
}
Outputs:
Tue Aug 18 14:00:00 CEST 2009 Tue Aug 18 15:00:00 CEST 2009
Symfony Form: unsetAllFieldsExcept()
When creating forms in symfony which extends from a Base (ORM) class, you sometimes do not need all fields that Propel/Doctrine generates for you. If you want to remove them you have several ways to do so.
1. Unset the fiels you don't need.
public function configure() {
unset($this['field1'], $this['field2'], ... );
}
Simple way to remove the fields you don't want, but if you change something in your database, which has an impact on that form (new column, foreignkey, etc ), it will be added in the (generated) super class. And if you don't update the unset function with that extra field, it will be expected in the form. Unless you have unit tests for all your forms this could brake it without knowing it.
2. Override the setup function.
/**
* @override
*/
public function setup()
{
parent::setup();
$this->setWidgets(...);
$this->setValidators(...);
}
Another way is to override the setup function and do your own widgets and validators initialization. This is a good way to only intialize the fields you really need, but you'll have to do what your ORM generated for you.
3. Use a function which unsets all fields except the one you need (like the enableAllPluginsExcept function).
$this->unsetAllFieldsExcept(array(
'field1',
'field2',
'field3',
...));
This would be usefull, because it will remove all fields you do not want to use, and even if new fields are added it will not use them. The drawback is that if you have 20 fields and only need to unset one of them, you'll have more type work
.
Since it does not exist in symfony, I quickly created our own function. This function should be added in the class BaseFormPropel.class:
abstract class BaseFormPropel extends sfFormPropel
{
public function setup() {
}
protected function unsetAllFieldsExcept($fields = array()) {
$unsetFields = array_diff(array_keys($this->getWidgetSchema()->getFields()), $fields);
foreach($unsetFields as $value) {
unset($this[$value]);
}
}
}
Which one to use ?
None of them are better. But if you need to reset a majority of the fields the ORM has generated then I would go for the method 2. If you only need to unset the fields you do not want to use then I would use the function unsetAllFieldsExcept().
Which method do/would you use ?
PHP DOMDocument: Convert Array to Xml
Recently I start working on an export module to invoice applications. One of them uses a very simple xml structure (simple nodes without attributes etc.) and therefore I wanted to create this xml also in a very simple way: from an array.
I decided the use DOM, and not e.g. SimpleXML, because I need to validate my xml with a schema.
After a quick search on the internet I found several snippets that could do the trick until I had to set the same element tag name on the same level:
<nodes> <node>text</node> <node>text</node> </nodes>
The snippets I found use the index of an array to create the name of the element and the value for the text part. Only everyone knows that you cannot set 2 keys with the same name in an array.
So what could we do to improve this ?
Symfony Forms Framework: Merge 2 forms
Recently I had to create a form to create/update users in our system. Some time ago we decided to save are users in 2 tables. The first table would contain all login information and the second his personal information. This is a simple example of the DB design:

User db design
I would not recommend doing this for so little fields. But in our system we have a lot more fields, and it helps us to optimize our queries.
Wouldn't it be better if we could merge the 2 forms? The answer is yes. And it's pretty easy to do so in Symfony ... too bad that it’s not documented on the Symfony website.
Symfony Forms Framework: Change validators at runtime.
Let’s say you have to make a user form with password fields. When you create the user you want the password fields to be required, but on an update the password fields should be optional because you don’t want the user the fill in his password on each update.
This is tricky because in the symfony forms Framework you have to predefine your validators. Your form would look like this:
class UserForm extends BaseUserForm {
public function configure() {
// Widgets
$this->widgetSchema['password'] = new sfWidgetFormInputPassword();
$this->widgetSchema['password_again'] = new sfWidgetFormInputPassword();
// Validators
$this->validatorSchema['password']->setOption('required', false);
$this->validatorSchema['password_again'] = clone $this->validatorSchema['password'];
$this->widgetSchema->moveField('password_again', 'after', 'password');
$this->mergePostValidator(new sfValidatorSchemaCompare('password', sfValidatorSchemaCompare::EQUAL, 'password_again', array(), array('invalid' => 'The two passwords must be the same.')));
}
}
In this signature of the form I defined the password and password_again field as optional, which is correct for an update of the user, but incorrect for the creation of the user. How the hell can I change the validator of the password field when I create a user ?
Well thanks to the good and well designed framework of symfony it is very simple
.
class UserForm extends BaseUserForm {
public function configure() {
// Widgets
$this->widgetSchema['password'] = new sfWidgetFormInputPassword();
$this->widgetSchema['password_again'] = new sfWidgetFormInputPassword();
// Validators
$this->validatorSchema['password']->setOption('required', false);
$this->validatorSchema['password_again'] = clone $this->validatorSchema['password'];
$this->widgetSchema->moveField('password_again', 'after', 'password');
$this->mergePostValidator(new sfValidatorSchemaCompare('password', sfValidatorSchemaCompare::EQUAL, 'password_again', array(), array('invalid' => 'The two passwords must be the same.')));
}
public function bind(array $taintedValues = null, array $taintedFiles = null) {
if ( $this->object->isNew() ) {
$this->validatorSchema['password']->setOption('required', true);
}
parent::bind($taintedValues, $taintedFiles);
}
}
What I did is override the function bind and before calling the bind method of the parent, I checked if the user object is new (means that we create a user) and if this is the case set the required option of the password field to true.
Storing multiple data in 1 database field with PHP serialize / unserialize
While the serialize/unserialize functions exists since the early PHP 4 version, I ignored its existence. I discovered it recently doing some research on how to store multiple data in 1 database field.
Before continuing, keep in mind that it's not always recommended to store multiple data in a database field, because it will be very difficult, if not impossible, to create queries using the inserted data. All serialized data will have to be unserialized, which takes time.
But why did I use it ?
The website I work on has a widget system (like netvibes and igoogle). Each widget has default settings that can be altered by a user. Those changes need to be saved in a database, so the next time the user loads the widget it will make use of the new settings.
When I first had to create this, I did not know of serialization in php, so I created the following db structure. (trying to respect DB Normalization).
You can see that I have a table with a list of widgets and a list of possible settings. Those two tables are connected to a widgetSetting table where the value of a setting to a widget is stored. It worked perfectly but it is not so proficient :
* To retrieve a widget's settings, you need to join 2 tables.
* To insert new widget settings, you need to check the settings table if a setting exists or not.
* When updating widget settings, you need to check if a setting is still used or not.
This is a lot of work and database complexity for something that only is used for saving/retrieving settings of a widget. In my case it would be much better if I could save those settings in 1 field in the widget table.
This is how I serialize my settings :
$settings = array(
'itemsOnPage' => 30,
'showChart' => true,
'startDate' => '01-10-2008',
'endDate' => '31-10-2008'
);
$serializedSettings = serialize($settings);
/**
* outputs:
*
* a:4:{s:11:"itemsOnPage";i:30;s:9:"showChart";b:1;s:9:"startDate";s:10:"01-10-2008";s:7:"endDate";s:10:"31-10-2008";}
*
*/
The serialize function will generate a storable representation of my array.
Just save this string in a database field and the job is done. To rebuild the original array from this value you only need to call the unserialize function:
$storedRepresentation = 'a:4:{s:11:"itemsOnPage";i:30;s:9:"showChart";b:1;s:9:"startDate";s:10:"01-10-2008";s:7:"endDate";s:10:"31-10-2008";}';
$settings = unserialize($storedRepresentation);
/*
* print_r($settings) would give :
*
* Array
* (
* [itemsOnPage] => 30
* [showChart] => 1
* [startDate] => 01-10-2008
* [endDate] => 31-10-2008
* )
*/
As you can see the unserialize function correctly rebuild the original array.
It is also possible to serialize Objects with the exception of the built-in objects.
class MySettings {
private
$itemsOnPage = 30,
$showCart = true,
$startDate = '01-10-2008',
$endDate = '31-10-2008';
public function getItemsOnPage() {
return $this->itemsOnPage;
}
}
$mySettingsSerialized = serialize(new MySettings());
$mySettings = unserialize($mySettingsSerialized);
echo $mySettings->getItemsOnPage(); // 30
When serializing objects, PHP will attempt to call the member function __sleep() prior to serialization. This is to allow the object to do any last minute clean-up, etc. prior to being serialized. Likewise, when the object is restored using unserialize() the __wakeup() member function is called.
class MySettings {
private
$itemsOnPage = 30,
$showCart = true,
$startDate = '01-10-2008',
$endDate = '31-10-2008';
public function getItemsOnPage() {
return $this->itemsOnPage;
}
public function __wakeup() {
$this->itemsOnPage *= 10;
}
}
$mySettingsSerialized = serialize(new MySettings());
$mySettings = unserialize($mySettingsSerialized);
echo $mySettings->getItemsOnPage(); // 300
So you see it is very simple to use the seriailize/unserialize functions in php. But like I said in the beginning of the post, use it wisely when storing the serialized value in a database. I only use it when I do not need the value for creating sql queries.
Symfony: How to refactor

Last year, my team and I, needed to create a new web application. We decided to make use of a well known PHP framework called Symfony. Not because some say this is the best framework, but because ...
- It is Enterprise Ready
- Has many plug-ins available
- It is Actively developed
- (most important) A great community and documentation
- Integrated Unit Testing
Although symfony has a good implemented MVC architecture with a lot of helpful functions, it is still very easy to make some design mistakes, like the DRY (Do not Repeat Yourself) principle. Fabien Potencier, lead developer of symfony, recently refactored an existing web project which he wrote down in the symfony blog.
If you work with symfony, you really should read this refactoring session because I’m pretty sure somewhere in your code you made the same mistake(s).
Call the expert: A refactoring story (Part 1, Part 2, Part 3, Part 4, Part 5)


