It’s Easy! But it’s something we all have run into, and when we do we are filled with the dreaded realization that we have to use our brains again. I imagine a perfect world where we all use our brains as little as possible, and so, I give you the sfProtocolFilter. It requires three easy steps. Allow me to explain:
1) Download the class file. You can find the code here. You can put this class wherever, but I prefer to put it in /path/to/project/apps/myapp/lib/sfProtocolFilter.class.php.
2) Activate the filter in your application:
#/path/to/project/apps/myapp/config/filters.yml
#...
# insert your own filters here
protocol:
class: sfProtocolFilter
3) Turn SSL on in your application:
#/path/to/project/apps/myapp/config/app.yml
prod:
protocol:
secure: off
Make sure you only turn this on for your production environment, especially if you have a local dev install. You’ll be redirected to a nonexistent server if you activate this locally.
And that’s it! Now every time somebody visits your application, they’ll be redirected to a Secure Socket Layer. And you have managed to leave your brain out of the equation.
Well, BarCampNashville ‘09 is over. The afternoon included free beer, a mechanical bull, and lots and lots of tech talk. Travis Roberts and I presented our session in the form of a blood-boiling feud between Symfony and Rails, Ruby and PHP. In reality, both of us were very respectful, and have still remained friends (although I did put Belgian Flesh-Crabs under his bed).
Here are some photos of the event, but really all you need is this spellbinding image:

No, I am not offering Travis a joint with my left hand… It’s a mic for the U-Stream feed. Thanks to everyone who came out and supported us, to everyone who came out to Bar Camp Nashville, and to Bar Camp Nashville for letting us present! What a great event. A lot of local developers showed up, and it was a blast.
I thought some of you symfony developers out there might appreciate the following form validators. They have been incredibly convenient, and were incredibly simple to write. I hope they come in handy:
- sfValidatorPhone: Validates a phone number using regex
- sfValidatorZip: Validates a zip code using regex
- sfValidatorUrl: Validates a url using regex
- sfValidatorCCExpirationDate (1.2, 1.4): validates the month/year on a credit card. Goes well with sfWidgetFormCCExpirationDate.
- sfValidatorCreditCardNumber: validates a credit card number with an optional card type parameter.
- sfValidatorCoupon: Used in payment forms to validate a coupon
What other useful validators should I include?
***** UPDATE *****
Symfony versions 1.3 and 1.4 broke backwards compatibility with some of these validators. I’ve added a link to each symfony version to fix this.
I just posted to the Centresource code blog about form testing in Symfony. Check it out:
Testing forms in Symfony can be a pain. The form framework form tester is an awesome tool, but it is a pain to fill out each form field for every form test you want to run. It is tedius, looks messy, and can be hard to maintain. I wrote a helper class to put filling in of unimportant form fields out of site and out of mind
Read the rest here.
Symfony makes good use of the flat-string array syntax, a sudo-serialization technique. This is great for objects that may require different options based on other column values (such as a “type” column). The synax works like this:
this=that
key=value
something=Something Else
This flat string is then parsed into an associative array with the sfToolkit::stringToArray() method. Using this, we can translate these values into the form framework by creating an OptionsForm class. The class will parse the values into individual fields, and provide widgets for the users to edit. When bound, the form will collapse these values back into a flat string.
The first step is to create an option form that extends the sfForm class:
class sfOptionsForm extends sfForm
Next, allow the options string (or array) to be passed in via the constructor:
public function __construct($defaults)
{
// convert options string to array
if(!is_array($defaults))
{
$defaults = sfToolkit::stringToArray($defaults);
}
$this->option_defaults = $defaults;
return parent::__construct();
}
Then, override the setup method to create basic widgets and validators.
public function setup()
{
foreach ($this->option_defaults as $field => $default)
{
$this->widgetSchema[$field] = new sfWidgetFormInput();
$this->validatorSchema[$field] = new sfValidatorString(array('required' => false));
}
$this->setDefaults($this->option_defaults);
}
That’s it! I would recommend extending this form in order to customize your widgets, but this is enough to get you started. Now, you need to add some methods to the form in order for the binding to be successful. In this example, we are using sfOptionsForm for an object field called “options”. In our parent form, we need to set this same field to our new form.
$this->embedForm('options', new sfOptionsForm($this->getObject()->getOptions());
The trickiest part of this whole process occurs when the form is bound. In order for this to function properly, we need to override our parent form’s bind() method.
public function bind(array $taintedValues = null, array $taintedFiles = null)
{
// do special binding for options if options exist
if (array_key_exists('options', $taintedValues) && array_key_exists('options', $this->embeddedForms))
{
// Flattens the option form into a string
$taintedValues['options'] = $this->embeddedForms['options']->getFlattenedValues($taintedValues['options']);
// unset imbedded form, replace field with a string widget / validator
unset($this['options']);
$this->widgetSchema['options'] = new sfWidgetFormInput();
$this->validatorSchema['options'] = new sfValidatorString();
}
$ret = parent::bind($taintedValues, $taintedFiles);
return $ret;
}
There are a few snags with this method. One occurs when a form does not validate on save. Since we unset the embedded form, we have to re-embed the form if the form is invalid. This can be rectified by adding code after the parent::bind() method in our code above.
public function bind(array $taintedValues = null, array $taintedFiles = null)
{
// ...
$ret = parent::bind($taintedValues, $taintedFiles);
{
$this->isBound = false; // form must be unbound in order to embed a form
$this->embedForm('options', new sfOptionsForm($this->getObject()->getOptions()); // re-embed the form
}
return $ret;
}
And there you have it! You now have a dynamic form-building interface. In order for your dynamic forms to be ironclad, there are still a few hidden snags you should be aware of. First, you need to make sure default options always get passed to the sfOptionsForm class. If an empty string is passed, the embedded form will be empty. Secondly, you need to take into consideration what happens when new fields are added, or the type of your object is switched. I usually implement a check to ensure the proper options are being passed for the dynamic form type.
To see these forms in action, install the csDoctrineSlideshowPlugin, or view the code straight from the repo.