After skimming through Fabien’s very interesting slideshare presentation on PHP 5.3 (no, I can’t read French), and playing with Jon Wage’s PHP Interactive Terminal, I whipped up a fun little object-oriented array-wrapper class to do some neat ruby-esque things. It should be noted this code is for fun, and probably not sufficient for production use.
Using my array class, the following functions are now possible:
// Instantiate the object
$test = new A(1, 2, 3, 4, 5, 6, 8, 10, 20);
// return an array containing the multiples of 4
$test->reduce(function($i) { return $i%4==0; });
// Sum up all even values
$x = 0;
$test->each(function($i) use (&$x) {
if($i % 2 != 0)
continue;
$x+=$i;
});
echo $i; // outputs "42";
// return the index of the first item evaluated true
$isGreaterThan = function($x, $y) { return $x > $y; };
$test->match(function($i) use ($isGreaterThan) { return $isGreaterThan($i, 15); });
// returns an array of all values multiplied by two
$test->map(function($i) { return $i*2; });
// until the function evaluates true, execute the block on all variables
$test->until(function($i) { return $i > 15; })->do(function($i) {
echo "This number ($i) is less than or equal to 15";
});
Although we really gain nothing here we don’t already have with functions such as array_walk, array_map, array_filter, and so on, I personally get slightly aroused at this ruby-esque PHP implementation. While not quite as pretty as ruby blocks, anonymous functions (aka “closures”) offer similar functionality. To make it more rubyesque, I’ve overloaded my class’s __call, and __invoke methods:
// Instantiate an existing array
$test = new A($fortunes);
// return an array with "in bed" appended to all fortunes
$test->map(function($i, $key) { return $i." in bed."; });
// mutate the array object in place (similar to ruby's exclamation mark convention)
$test->_map(function($i, $key) { return $i." in bed."; });
// the underscore convention works for all functions that return an array
$test->_reduce(function($i, $key) { return strpos($i, 'happiness') !== false; });
// Ruby-like array access
$test = new A(10, 900, 5, 30);
echo $test(1, 2) // returns array [900, 5] (starts at index 1, length is 2)
// maybe supported someday, if I have time:
echo $test['0..2'] // returns array [10, 900, 5] (starts at index 0, up to index 2)
echo $test['1..,-1'] // returns array [10, 900, 5] (starts at index 0, up to last index, excludes ending index)
$test['2...3'] = new A(2, 2); //inserts array as the given indexes, to produce array [10, 900, 2, 2, 2, 20]
You can check out my half-baked class here. Any other fun ideas??
*** Update ***
Jwage did something similar by wrapping primitive types in php classes. Check out his code here!
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 had the honor of leading the Nashville Symfony Users Group this past Thursday for our September monthly meetup. We met in the Centresource conference room to discuss the extension of the Symfony routing framework. I lead the talk, but it did not take long for the presentation to become a round table discussion, with everyone contributing their own thoughts and snippets of Symfony wisdom. Overall, the session was a lot of fun. You can view the slideshow from the presentation here.
Doctrine 2.0 was also discussed. We are hoping for a more complete presentation from Jon Wage next month. Keep your fingers crossed!
Symfony Form Framework – Requiring At Least One of Many Fields
In my application there are three places for the user to specify an amount, all of which constitute the final cost. No single one of these fields are required, but at least one needs to be completed for the form to validate. Unfortunately, the Form Framework allows only one field per validator. That is, unless you use the sfValidatorSchema::setPostValidator() option. This method will allow you to set a validator on your entire schema, and is how password validation works. You set the sfValidatorSchemaCompare() validator using this method, and it compares two fields to be equal.
Using this method, I created a class called sfValidatorSchemaVariableRequired that accepts an array in the constructor for all the widgets you are referring to, and also the minimum number required out of that list (default is 1). Here is an example of it used below:
$this->validatorSchema->setPostValidator(
new sfValidatorSchemaVariableRequired(array('college_amount', 'capital_amount', 'other_amount')));
This will check the three fields passed in the array and ensure at least 1 of them has been completed. This takes place after other validation, so you can still validate the data beforehand (for instance, I use sfValidatorInteger for all three fields).
Your form by default renders like this:

You can of course change all of the validator messages. You can hide the global message all together. I prefer to pass a list of labels to the constructor like this:
$this->validatorSchema->setPostValidator(
new sfValidatorSchemaVariableRequired(
array('college_amount', 'capital_amount', 'other_amount'),
array('labels' => array('Annual Fund Gift Amount', 'Capital Gift Amount', 'Other Gift Amount')),
array('global_invalid' => 'You must fill out at least %num_required% of the following fields: %labels%')));
Which will then render your error in this way:

Here is the code for the class itself, which you can pull from github here
*/
class sfValidatorSchemaVariableRequired extends sfValidatorSchema
{
/**
* Constructor.
*
* Available options:
*
* * num_required: minimum amount of fields that must pass validation (default is 1)
* * field_labels: field labels passed to the global_invalid message
*
* Available messages:
*
* * global_invalid: Global error thrown for the form
*
* @param string $fields Array of fields to choose from. These values are also passed to the global_invalid message
* @param array $options An array of options
* @param array $messages An array of error messages
*
* @see sfValidatorBase
*/
public function __construct(array $fields, $options = array(), $messages = array())
{
$this->addOption('num_required', 1);
$this->addOption('fields', $fields);
$this->addOption('labels', array());
$this->addOption('throw_global_error', true);
$this->addMessage('invalid', 'You must fill out at least %num_required% of these fields');
$this->addMessage('global_invalid', 'You filled out %num_valid% of %num_required% required fields below');
parent::__construct(null, $options, $messages);
}
/**
* @see sfValidatorBase
*/
protected function doClean($values)
{
$valid = 0;
foreach ($this->getOption('fields') as $field) {
$valid += (isset($values[$field]) && $values[$field]) ? 1:0;
}
if ($valid < $this->getOption('num_required'))
{
$errorSchema = new sfValidatorErrorSchema($this);
if ($this->getOption('throw_global_error'))
{
// Add global error
$errorSchema->addError(new sfValidatorError($this, 'global_invalid', array(
'num_required' => $this->getOption('num_required'),
'num_valid' => $valid,
'fields' => implode(', ', $this->getOption('fields')),
'labels' => implode(', ', $this->getOption('labels')),
)));
}
$error = new sfValidatorError($this, 'invalid', array('num_required' => $this->getOption('num_required')));
// Add an error for each of the fields
foreach ($this->getOption('fields') as $field)
{
$errorSchema->addError($error, $field);
}
throw $errorSchema;
}
return $values;
}
}
This class only checks that at least one or more fields has a value. I can think of a few other group validators, such as having one or more fields match a passed validator, or passed individual validators. Can you think of any other useful Post Validators?