When I work in Drupal, I do things programmatically as much as possible. This keeps features out of the database, which makes version control, maintainability, portability, and deployment so much easier. There are exceptions though; I find it’s worthwhile to use the GUI for adding fields to node content types. When it comes to field content display however, I always do it in code.
A challenge I came upon recently was needing to get the human-readable value of a text list field. This is the kind of field that’s set in the CMS using a dropdown or radio select, with a preset list of options.
The field settings have an “Allowed values list”, which is a set of key|label
pairs. The key
is the unchanging machine name, and the label
is the human-readable, frontend facing value, which can be changed whenever necessary.
The “Allowed values list” might look like this:
cow|Moo Cow
dog|Doggie
pig|Piggie
Now, the goal is to be able to easily access the human-readable value programatically, so that we can display the label
part whenever we need it, without having to monkey around configuring the field’s display settings.
Create and enable a custom module named mymodule
. I won’t go into the details of how to set up a base custom module, if you need help with this, there are plenty of resources out there.
In your custom module, create:
modules/mymodule/src/Plugin/Field/FieldType/MyListStringItem.php
Place the follwing code in it:
<?php
namespace Drupal\mymodule\Plugin\Field\FieldType;
use Drupal\options\Plugin\Field\FieldType\ListStringItem;
// extend the base class
class MyListStringItem extends ListStringItem {
public function getHumanValue() { // add our custom method
$allowed_values = $this->getSetting('allowed_values');
$value = $allowed_values[$this->value];
return $value;
}
}
In modules/mymodule/mymodule.module
use the hook hook_field_info_alter
to tell Drupal to use our class MyListStringItem
for list_sting fields:
/* Implements hook_field_info_alter */
function mymodule_field_info_alter(&$info) {
// this makes `list_sting` fields use our custom class,
// which extends the base Drupal class for the field.
if (isset($info['list_string']))
$info['list_string']['class'] =
'Drupal\mymodule\Plugin\Field\FieldType\MyListStringItem';
}
Flush the cache.
Now you can easily get the human readable value whenever you need it, like this:
$value = $node->field_my_list_string[0]->getHumanValue();
Or in a twig template:
The value is {{ node.field_my_list_string.0.getHumanValue }}
Nice!
There’s a catch though, this will only do the trick on a single-language site. In the next post, I’ll talk about how to get the translated human readable value.