Creating a custom filter in Drupal Views for monthly filtering

Components

This snippet provides a custom Views filter for Drupal, enabling users to filter nodes by the month of their publication date. It adds a user-friendly dropdown in the Views UI, allowing easy selection of a month to filter content.

The hook_views_data() hook in Drupal is used to define how a module exposes database tables to Views.

/**
 * Implements hook_views_data().
 */
function MY_MODULE_views_data() {
  $data = [];

  $data['views']['month_filter'] = [
    'title' => t('Month filter - Custom Filter'),
    'filter' => [
      'title' => t('Month filter - Custom Filter'),
      'field' => 'created',
      'id' => 'month_filter',
    ],
  ];

  return $data;
}

To correctly implement your custom filter plugin in Drupal, you should place the code in the MY_MODULE/src/Plugin/views/filter directory. Below is an example of how your plugin code might look:

<?php

namespace Drupal\MY_MODULE\Plugin\views\filter;

use Drupal\Core\Form\FormStateInterface;
use Drupal\views\Plugin\views\filter\FilterPluginBase;

/**
 * Filters nodes by month of publish date.
 *
 * @ViewsFilter("month_filter")
 */
class MonthFilter extends FilterPluginBase {

  /**
   * {@inheritdoc}
   */
  public function adminSummary() {
    return $this->t('Filters nodes by month of publish date.');
  }

  /**
   * {@inheritdoc}
   */
  protected function valueForm(&$form, FormStateInterface $form_state) {
    $form['value'] = [
      '#type' => 'select',
      '#title' => $this->t('Month'),
      '#options' => [
        'january' => $this->t('January'),
        'february' => $this->t('February'),
        'march' => $this->t('March'),
        'april' => $this->t('April'),
        'may' => $this->t('May'),
        'june' => $this->t('June'),
        'july' => $this->t('July'),
        'august' => $this->t('August'),
        'september' => $this->t('September'),
        'october' => $this->t('October'),
        'november' => $this->t('November'),
        'december' => $this->t('December'),
      ],
      '#default_value' => $this->value,
    ];
  }

  /**
   * {@inheritdoc}
   */
  public function query() {
    $this->ensureMyTable();

    /** @var \Drupal\views\Plugin\views\query\Sql $query */
    $query = $this->query;

    if (!empty($this->value[0])) {
      $month_num = date('m', strtotime($this->value[0]));
      $query->addWhereExpression(0, "EXTRACT(MONTH FROM FROM_UNIXTIME(node_field_data.created)) = :month", [':month' => $month_num]);
    }
  }

}

Clear the caches after implementation, and then add the custom filter to a View used to display nodes.

About the Author

Goran Nikolovski is an experienced web and AI developer skilled in Drupal, React, and React Native. He founded this website and enjoys sharing his knowledge.