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 a web and AI developer with over 10 years of expertise in PHP, Drupal, Python, JavaScript, React, and React Native. He founded this website and enjoys sharing his knowledge.