Custom sort handler
22. Custom Sort Handler
When to Use
Custom sort logic: computed fields, weighted sorting, multi-column sorts, integration with external ranking systems.
Steps
-
Create sort plugin — In
src/Plugin/views/sort/MyCustomSort.phpnamespace Drupal\mymodule\Plugin\views\sort; use Drupal\views\Plugin\views\sort\SortPluginBase; use Drupal\views\Attribute\ViewsSort; #[ViewsSort("my_custom_sort")] class MyCustomSort extends SortPluginBase { public function query() { $this->ensureMyTable(); $this->query->addOrderBy( $this->tableAlias, $this->realField, $this->options['order'] ); } } -
Multi-field sort — Add multiple ORDER BY clauses
public function query() { $this->ensureMyTable(); // Sort by status first, then title $this->query->addOrderBy($this->tableAlias, 'status', 'DESC'); $this->query->addOrderBy($this->tableAlias, 'title', $this->options['order']); } -
Computed sort — Use SQL expressions
public function query() { $formula = "LENGTH($this->tableAlias.$this->realField)"; $this->query->addOrderBy(NULL, $formula, $this->options['order'], $this->tableAlias . '_length'); } -
Integrate with hook_views_data()
function mymodule_views_data() { $data['node_field_data']['custom_weighted_sort'] = [ 'title' => t('Weighted sort'), 'sort' => ['id' => 'my_custom_sort'], ]; return $data; }
Decision Points
| At this step... | If... | Then... |
|---|---|---|
| query() | Sorting by DB field | Use addOrderBy($table, $field, $order) |
| query() | Sorting by formula | Pass NULL as table, formula as field |
| query() | Multi-column sort | Call addOrderBy() multiple times in desired order |
| options form | User-configurable sort | Override defineOptions() and buildOptionsForm() |
Common Mistakes
- Wrong ORDER BY sequence → Last addOrderBy() call is highest priority; add primary sort last
- Missing alias parameter in formula sorts → Fourth parameter required for SQL expression sorts
- Not respecting $this->options['order'] → User's ASC/DESC choice should be honored
- Sorting by unindexed columns → Performance disaster on large datasets; ensure DB indexes exist
- Overriding parent::query() → Call parent::query() or reimplement ensureMyTable() logic
See Also
- Section 10: Sort & Contextual Filters — configuration approach
- Reference:
core/modules/views/src/Plugin/views/sort/SortPluginBase.php - Reference:
core/modules/views/src/Plugin/views/sort/Random.php— formula-based sort example