Drupal List Fields allowed_values_function == Custom Display Values

We had a simple problem and Drupal provided a simple (but very obscure and hard to find) solution. So I thought I would blog about it.

The Situation: We had a data value that called for a List Integer Field. The list was a set of rankings low to high. An integer list would allow the ranking value to be the internal id and a human readable label was the display value. The ranking value was to be used in some formula calculations. So it was important to fix the size of the list (5 entries in this case) so that the math worked. Perfect use case for a List Integer field.

The Problem: The application was a Multi Tenant SaaS system and each client needed to be able to provide their own label (display value). In this case generic labels like "low", "medium" and "high" were of little value since the levels in the list where specific financial dollar thresholds. For small companies a top rank may involve $1 Million. For a very large company the top rank could easy be $1 Billion. We could either provide generic one-size-fiits-all labels AND provide additional help text describing what each label meant. OR we could provide meaningful labels. The need was simple: provide a fixed list and allow each client to provide their own informative display label.

The (not so obvious) Solution: allowed_values_function - Finding this was very difficult! Hence the reason for this post.

I spent a few hours Googling away with various phrases attempting to discover if Drupal provided a simple solution to my problem. Nothing came close. I had visions of a mess of finely hand crafted hook_form_alter's and custom node templates and then shuddered when I realized View support would be required as well.

Unless I could solve it at the field level, this could get very messy. But there must be a simple solution. After all, the List field was able to store and provide the list of display values. Maybe I would need to clone a custom version of List Integer field?

This spurred me to actually split a field open and take a look under the covers. I added a List Integer field to a test content type in a fresh Drupal install, gave it a set of nice keys and display values and then went hunting in the database. I found my keys and values in a row of the field_config table under "allowed_values" column. More interesting was the next column: "allowed_values_function". Grepping the Drupal code base gave tons of hits. All of them setting this value to an empty string as part of defining a field. Dead ends.

I finally hit the jackpot in list.test.

'allowed_values_function' => 'list_test_dynamic_values_callback'

A grep of list_test_dynamic_values_callback revealed that Drupal fully supported the concept I required. It just did not document or reveal it very well.

I had THE solution and a working example. Time to write some code...