we created a custom Field Type (data storage) and built a Field Widget (data input).
Now we complete the field system by building the final layer: Field Formatters.
If a field type defines how data is stored and a widget defines how data is entered, a field formatter defines how data is displayed.
Field formatters control:
- How field values are rendered
- How values appear in different view modes
- How output is structured
- How presentation remains separate from storage
This topic continues extending the same weeklydrupal_demo module and the custom rating field we previously created.
By the end of this article, you will understand:
- What a field formatter is
- How formatters connect to field types
- How to create a custom formatter plugin
- How Drupal renders field output
- Why separating storage and presentation matters
1. What Is a Field Formatter
A field formatter controls how field data appears when viewing an entity.
Examples you already know:
- A text field can display as plain text or trimmed text
- A boolean field can display as "Yes/No" or "True/False"
- An entity reference can display as a label or a linked label
The same field type can have multiple formatters.
In simple terms:
Field Type = how data is stored
Field Widget = how data is entered
Field Formatter = how data is displayed
2. Where Field Formatters Live
Field formatter plugins live in:
src/Plugin/Field/FieldFormatter
Drupal discovers them using annotations.
3. Creating a Formatter for the Rating Field
We will create a formatter that displays stars instead of numbers.
File path
weeklydrupal_demo/src/Plugin/Field/FieldFormatter/RatingStarsFormatter.php
Code
<?php
namespace Drupal\weeklydrupal_demo\Plugin\Field\FieldFormatter;
use Drupal\Core\Field\FieldItemListInterface;
use Drupal\Core\Field\FormatterBase;
/**
* Plugin implementation of the 'rating_stars_formatter' formatter.
*
* @FieldFormatter(
* id = "rating_stars_formatter",
* label = @Translation("Rating Stars"),
* field_types = {
* "rating"
* }
* )
*/
class RatingStarsFormatter extends FormatterBase {
public function viewElements(FieldItemListInterface $items, $langcode) {
$elements = [];
foreach ($items as $delta => $item) {
$value = $item->value;
$stars = str_repeat('★', $value);
$elements[$delta] = [
'#markup' => $stars,
];
}
return $elements;
}
}
4. Understanding the Annotation
@FieldFormatter(
id = "rating_stars_formatter",
label = @Translation("Rating Stars"),
field_types = { "rating" }
)
Explanation:
id– Machine name of the formatterlabel– Appears in field display settingsfield_types– Defines which field types this formatter supports
This connects the formatter to the rating field type.
5. The viewElements() Method
public function viewElements(FieldItemListInterface $items, $langcode)
This method:
- Receives stored field values
- Loops through them
- Returns a render array
Drupal handles:
- Caching
- Theming
- View modes
- Integration with Views and REST
6. Understanding $items and $delta
$itemscontains all values of the field$deltarepresents each value’s index
For multi-value fields, the formatter must handle multiple entries.
7. How Drupal Uses Formatters
When viewing an entity:
- Drupal loads the entity
- Retrieves field values
- Looks up the selected formatter
- Calls
viewElements() - Merges render arrays into the final page
The formatter never touches database logic. It only controls output.
8. View Modes and Display Configuration
Field formatters can be selected per view mode:
- Full content
- Teaser
- Custom view modes
Each mode can use a different formatter.
This gives Drupal strong flexibility in presentation.
9. Formatter Settings
Formatters can define configurable settings.
Example:
public static function defaultSettings() {
return [
'show_max' => TRUE,
] + parent::defaultSettings();
}
These settings appear in the "Manage Display" UI.
10. Separation of Responsibilities
Field system architecture encourages separation:
- Field Type = storage
- Widget = input
- Formatter = output
This separation ensures:
- Clean architecture
- Reusability
- Flexibility
- Scalability
11. Common Mistakes to Avoid
- Performing business logic inside formatters
- Hardcoding presentation that belongs in themes
- Ignoring multi-value behavior
- Returning strings instead of render arrays
Formatters should focus on transforming stored data into renderable output.
12. Learning by Building: weeklydrupal_demo
Our demo module now includes:
- Custom field type
- Custom widget
- Custom formatter
We now have a complete custom field system.
Next topics will expand into:
- Entity CRUD
- Typed Data API
- Advanced backend processing
13. Why Field Formatters Matter
Understanding field formatters allows you to:
- Build flexible display systems
- Support multiple view modes
- Integrate with Views cleanly
- Separate data modeling from presentation
This is a key concept for backend Drupal developers who design scalable content systems.