Practical Functional PHP
There are a lot of articles on internet about functional PHP. There is very nice presentation about it http://munich2012.drupal.org/program/sessions/functional-php that was held in Munich.
I was thinking about applying techniques to every-day coding and came up with two quite useful examples.
Cleaner code in form builders
Usually functions that generate form arrays are big. Sometimes they are very big and it is getting complicated to understand fast what elements are in the form and what are their properties.
This example is trying to address this problem.
<?php
$textfield = array('#type' => 'textfield');
$required = array('#required' => TRUE);
$size = function($number) { return array('#size' => $number); };
$size_maxlength = function($number) { return array('#size' => $number, '#maxlength' => $number); };
$form['first_name'] = $textfield + $size(20);
$form['last_name'] = $textfield + $size(20);
$form['business_name'] = $textfield + $size(20);
$form['account_number'] = $textfield + $required + $size(20);
$form['pin'] = $textfield + $required;
$form['ssn'] = $textfield + $required + $size_maxlength(4);
$form['phone_number_part1'] = $textfield + $required + $size_maxlength(3);
$form['phone_number_part2'] = $textfield + $required + $size_maxlength(3);
$form['phone_number_part3'] = $textfield + $required + $size_maxlength(4);
?>
Now it is pretty clear what elements are and what properties they have. If you will ask about default values or titles – default values are assigned to elements using
<?php
foreach ($form as $form_key => &$element_form) {
if (!isset($default_values[$form_key])) {
continue;
}
$value_key = ($element_form['#type'] == 'value') ? '#value' : '#default_value';
$element_form[$value_key] = $default_values[$form_key];
}
?>
And all the titles are set up in theming function for this form.
In this example I like how compact are form constructors and how easy they are to read.
Recursive iterating in form arrays
Second example is also related to forms.
Once I have needed to set all form sub elements to be not required. And there was another function that disables all elements.
So functions looked like:
<?php
function custom_module_form_element_recursive_disable(&$element) {
if (!is_array($element)) {
return;
}
$element['#disabled'] = TRUE;
foreach (element_children($element) as $key) {
custom_module_form_element_recursive_disable($element[$key]);
}
}
function custom_module_form_element_recursive_not_required(&$element) {
if (!is_array($element)) {
return;
}
if (!empty($element['#required'])) {
$element['#required'] = FALSE;
}
foreach (element_children($element) as $key) {
custom_module_form_element_recursive_disable($element[$key]);
}
}
?>
As you can see it is pretty simple code but there is a lot of duplicate in it.
Using functional php we can avoid duplicating:
<?php
function _custom_module_recursive_form_visitor(&$element, $function) {
if (!is_array($element)) {
return;
}
$function($element);
foreach (element_children($element) as $key) {
_custom_module_recursive_form_visitor($element[$key], $function);
}
}
function custom_module_form_element_recursive_disable(&$element) {
$function = function(&$element) {
$element['#disabled'] = TRUE;
};
_custom_module_recursive_form_visitor($element, $function);
}
function custom_module_form_element_recursive_not_required(&$element) {
$function = function(&$element) {
if (!empty($element['#required'])) {
$element['#required'] = FALSE;
}
};
_custom_module_recursive_form_visitor($element, $function);
}
?>
Now we can add other functions that need to perform actions recursively on form elements.
If you have some other usages of anonymous functions in PHP please share.
Thanks for reading.
By the way I have submitted a session for DrupalCon Portland http://portland2013.drupal.org/session/clean-code where I will touch this topic as well from perspective of keeping your code clean. So welcome to comment on it.
Tags: drupal planetphp