Tables part 2: Handlers and Option fields
The next 3 sections, Fields, Sorts and Filters all support handlers and option fields. This is a brief discussion of how those concepts work.
Handlers
All of the sections that follow will allow handlers. Handlers are callback functions that are similar to hooks, but instead of being pre-named functions that are called at certain times, they can be named whatever you like. Like hooks, however, they must fit a certain function signature. When specifing handlers, you treat the name of the function as a string. i.e,
<?php
'handler' => 'my_views_handler',
?>And later in your code, you will have:
<?php
function my_views_handler($arg1, $arg2, ...) {
?>Certain handlers can support arrays of handlers, giving the administrator the ability to choose which one is used. The documention for the handler will say if this is supported. If it is, you may use this format:
<?php
'handler' => array(
'my_views_handler' => t('Name of handler displayed to user'),
'my_other_handler' => t('Name of this option displayed to user'),
),
?>Views provides many common handlers that are useful to modules. These are described at the bottom of the section the handlers are relevant to.
Option and value fields
All of the data types in Views -- fields, sorts and filters -- support an 'option' field which will appear on the administrative UI. this allows the field to have all kinds of flexibility in how they work. For Fields, they can be additional control in how items are displayed; for filters, they can add flexibility in terms of extra options such as for 'between' or as deltas for date fields. Even sorts can occasionally make use of options by adding granularity options to date sorting.
The 'option' field tells Views how to present the form to fill it in. Left blank, there will be no form item; if set to 'string' or 'integer', a simple text field will be presented. Note that these are both actually the same thing as far as Views is concerned. It doesn't actually perform any additional validation to ensure the option is really an integer. If you need this, you're responsible for providing validation. This will probably be rectified in a future version of Views.
The 'option' field can also be given a Forms API array to present almost anything you like. Please be aware that the screen space devoted to this area is limited, but even given this it's possible to put in complex forms. Also, it is important that the '#value' returned by this be a simple string, which means that some extra steps may need to be taken if you want multiple options.
Constructing option fields
The most common Form API construct is a simple select widget:
<?php
'option' => array(
'#type' => 'select',
'#options' => array(
1 => t('Option 1'),
2 => t('Option 2'),
),
),
?>In order to get more complex values out of this, it's necessary to use a #process and an #after_build and serialize the result. For example:
<?php
'option' => array(
'option_1' => array(
'#type' => 'select',
'#options' => array(
1 => t('Option 1'),
2 => t('Option 2'),
),
),
'option_2' => array(
'#type' => 'textfield',
'#size' => 10,
),
'#type' => 'example_output',
'#process' => array('example_process' => NULL),
'#after_build' => array('example_after_build'),
),
..
/*
* just display the option
*/
function example_handler($fieldinfo, $fielddata, $value, $data) {
return $fielddata['options'];
}
/**
* The #process takes the serialized #default_value and feeds
* the forms beneath it.
*/
function example_process($element) {
$values = unserialize($element['#default_value']);
if (!is_array($values)) {
// set default values for options that have no stored value.
$values = array('option_1' => 1, 'option_2' => '');
}
$element['option_1']['#default_value'] = $values['option_1'];
$element['option_2']['#default_value'] = $values['option_2'];
return $element;
}
/**
* Put the value back.
*/
function example_after_build($element) {
$values = array();
$values['option_1'] = $element['option_1']['#value'];
$values['option_2'] = $element['option_2']['#value'];
$element['#value'] = serialize($values);
form_set_value($element, $element['#value']);
return $element;
}
/**
* this forces the #value to not be printed as it would be if we put in
* no #type.
*/
function theme_example_output($element) {
return $element['#children'];
}
?>Ok, catch your breath. That's a little bit complex, but once you get familiar with it, there's a lot that can be done.
Using the options
In the various handler functions, the option will be available as the 'options' field in $fielddata, $sortdata or $filterdata, depending upon which you're using. If you used a serialized array as above, you'll need to serialize it. Unless you're using a handler, Views doesn't do anything with this data by itself, so this one is all yours.
A little extra for 'value' fields
For filters, the 'value' field works exactly like 'option' fields, with one exception:
If the 'value' is a Form API array, and it is '#type' => 'select', and '#options' => 'a_function_name', it will call that function and use the resulting array as the options instead. This makes it easier to keep dynamic options available for the value fields without having to clear Views' cache just for this purpose.

Some thoughts...
1. In general, I'm left scratching my head a bit about what is a Handler vs. an Option vs. etc. Or maybe not necessarily what is each of them (since the technical explanation is sound) but rather when you'd use each of them and one over the other. A brief overview paragraph with a little use case would do me wonders. "Let's say your client asks for thing. A handler is useful when you want to do X with thing. If you want to do Y, then an option is the right choice."
2. I really liked how the last section used actual "real world" example code. It'd be cool if this one did too, rather than "my_handler" and "option 1" It looks like Node Title might be a place to start, as I notice it uses both of these.
3. Where do I stick that handler mapping code? I assume in my table definition since, hey, we're in the tables section. ;) But a little more context might be helpful.
4. This paragraph:
"Certain handlers can support arrays of handlers, giving the administrator the ability to choose which one is used. The documention for the handler will say if this is supported. If it is, you may use this format:"
left my head spinning a bit. Why only certain handlers? How do I tell if it's a handler that supports it or not? How do I make a handler for my module that supports arrays? Why would I want to or not want to? etc.
More to come, probably, just jotting things down as I come across them.
CCK View Handlers and Options
If you're writing or maintaining a CCK field type module, it's worth noting that you're allowed to create new view Options, but not Handlers (if CCK is providing automatic database storage). CCK provides a universal handler in content_views.inc which basically calls content_format() as the handler. This means that when working within CCK, your view 'Options' are defined in hook_formatter_info(). For example:
<?phpfunction mycustomcckfield_formatter_info() {
$formatters = array(
'plain' => array(
'label' => 'Plain Text',
'field types' => array('mycustomcckfield'),
),
'link' => array(
'label' => 'As a Link',
'field types' => array('mycustomcckfield'),
),
);
?>
will automatically create two options for the CCK field type 'mycustomcckfield': Plain Text and As a Link. The output to the view will match whatever is defined in mycustomcckfield_field_formatter().
Nathan Haug
creative graphic design w: quicksketch.org
& software development e: nate@quicksketch.org