Drupal Custom Views Development

Our company is engaged in the development, support and maintenance of sites of any complexity. From simple one-page sites to large-scale cluster systems built on micro services. Experience of developers is confirmed by certificates from vendors.
Development and maintenance of all types of websites:
Informational websites or web applications
Business card websites, landing pages, corporate websites, online catalogs, quizzes, promo websites, blogs, news resources, informational portals, forums, aggregators
E-commerce websites or web applications
Online stores, B2B portals, marketplaces, online exchanges, cashback websites, exchanges, dropshipping platforms, product parsers
Business process management web applications
CRM systems, ERP systems, corporate portals, production management systems, information parsers
Electronic service websites or web applications
Classified ads platforms, online schools, online cinemas, website builders, portals for electronic services, video hosting platforms, thematic portals

These are just some of the technical types of websites we work with, and each of them can have its own specific features and functionality, as well as be customized to meet the specific needs and goals of the client.

Showing 1 of 1 servicesAll 2065 services
Drupal Custom Views Development
Medium
from 1 business day to 3 business days
FAQ
Our competencies:
Development stages
Latest works
  • image_web-applications_feedme_466_0.webp
    Development of a web application for FEEDME
    1161
  • image_ecommerce_furnoro_435_0.webp
    Development of an online store for the company FURNORO
    1041
  • image_crm_enviok_479_0.webp
    Development of a web application for Enviok
    822
  • image_crm_chasseurs_493_0.webp
    CRM development for Chasseurs
    847
  • image_website-sbh_0.png
    Website development for SBH Partners
    999
  • image_website-_0.png
    Website development for Red Pear
    451

Developing Custom Drupal Views

Views is the most powerful tool in Drupal for displaying content lists. Filters, sorts, related entities, different output formats, ajax-pagination, exposed filters — everything is configured without code. Custom code is needed where UI isn't enough: custom filters, custom field formatters, programmatic query manipulation.

Creating View via UI

Path: /admin/structure/views/add. Main parameters:

  • View name — machine name, used in code
  • Show — entity type (Content, Users, Taxonomy terms...)
  • Tagged with — tag filter when creating
  • Display — Page (URL), Block, REST Export, Feed, Attachment

View Configuration in YAML

After UI setup export:

drush config:export
# creates views.view.{machine_name}.yml

Fragment of complex View configuration:

# views.view.news_list.yml
id: news_list
label: 'News List'
module: views
description: ''
tag: ''
base_table: node_field_data
base_field: nid
display:
  default:
    display_options:
      fields:
        title:
          id: title
          table: node_field_data
          field: title
          entity_type: node
          link_to_entity: true
          label: ''
          element_label_colon: false
        field_image:
          id: field_image
          table: node__field_image
          field: field_image
          image_style: news_teaser
          image_link: content
        created:
          id: created
          date_format: custom
          custom_date_format: 'd.m.Y'
      filters:
        status:
          value: '1'
          table: node_field_data
          field: status
        type:
          value: { news: news }
          table: node_field_data
          field: type
        field_category_target_id:
          id: field_category_target_id
          exposed: true
          expose:
            label: 'Category'
            identifier: category
      sorts:
        created:
          order: DESC
      pager:
        type: full
        options:
          items_per_page: 12
      style:
        type: html_list
      row:
        type: 'fields'
      use_ajax: true
  page_1:
    display_plugin: page
    path: /news
    display_options:
      menu:
        type: normal
        title: News

Exposed Filters (filters for user)

Exposed filters render as form — user can filter list without reload (with AJAX) or with reload. Configured in UI by checking "Expose this filter to visitors" for each filter.

Custom exposed filter handler via hook_views_query_alter:

// my_module.module

use Drupal\views\ViewExecutable;
use Drupal\views\Plugin\views\query\QueryPluginBase;

/**
 * Implements hook_views_query_alter().
 */
function my_module_views_query_alter(ViewExecutable $view, QueryPluginBase $query): void {
  if ($view->id() !== 'news_list') return;

  // Add additional condition based on GET parameter
  $price_from = \Drupal::request()->query->get('price_from');
  if ($price_from && is_numeric($price_from)) {
    $query->addWhereExpression(
      0,
      "node__field_price.field_price_value >= :price_from",
      [':price_from' => (float) $price_from]
    );
  }
}

Custom Row Style Plugin

Standard styles: Fields, Entity, HTML list, Table. For custom render — plugin:

// src/Plugin/views/row/ArticleCardRow.php
namespace Drupal\my_module\Plugin\views\row;

use Drupal\views\Plugin\views\row\RowPluginBase;
use Drupal\views\ResultRow;

/**
 * @ViewsRow(
 *   id = "article_card",
 *   title = @Translation("Article card"),
 *   help = @Translation("Renders articles as cards"),
 *   display_types = {"normal"},
 * )
 */
class ArticleCardRow extends RowPluginBase {

  public function render(ResultRow $row): array {
    $node = $row->_entity;
    $view_builder = \Drupal::entityTypeManager()->getViewBuilder('node');

    return [
      '#theme' => 'article_card',
      '#node' => $node,
      '#title' => $node->getTitle(),
      '#image' => $node->hasField('field_image')
        ? $view_builder->viewField($node->get('field_image'), 'card')
        : NULL,
      '#url' => $node->toUrl()->toString(),
      '#cache' => [
        'tags' => $node->getCacheTags(),
        'contexts' => ['user.roles'],
      ],
    ];
  }
}

Programmatic View Usage

use Drupal\views\Views;

// Get View programmatically and execute
$view = Views::getView('news_list');
$view->setDisplay('block_1');
$view->setArguments([42]); // contextual filter arguments
$view->setExposedInput(['category' => 'tech']);
$view->execute();

// Get results
$results = $view->result;
foreach ($results as $row) {
  $node = $row->_entity;
  // ...
}

// Render View block
$view->preExecute();
$view->execute();
$rendered = $view->buildRenderable('block_1');

Views and Custom Tables

If you need to show data from custom database table, register it for Views:

// my_module.views.inc

/**
 * Implements hook_views_data().
 */
function my_module_views_data(): array {
  $data = [];

  $data['my_module_stats']['table']['group'] = t('My Module');
  $data['my_module_stats']['table']['base'] = [
    'field' => 'id',
    'title' => t('My Module Stats'),
    'help' => t('Statistics data from my module'),
  ];

  $data['my_module_stats']['node_id'] = [
    'title' => t('Node ID'),
    'help' => t('Related node'),
    'relationship' => [
      'base' => 'node_field_data',
      'base field' => 'nid',
      'id' => 'standard',
      'label' => t('Node'),
    ],
    'filter' => ['id' => 'numeric'],
    'sort' => ['id' => 'standard'],
    'field' => ['id' => 'numeric'],
  ];

  $data['my_module_stats']['view_count'] = [
    'title' => t('View count'),
    'field' => ['id' => 'numeric'],
    'filter' => ['id' => 'numeric'],
    'sort' => ['id' => 'standard'],
  ];

  return $data;
}

REST Export Display

Views can export data to JSON via REST Export display:

/api/news.json?page=0&items_per_page=20&category=tech

Configured in UI or YAML. CORS headers configured in services.yml:

# web/sites/default/services.yml
cors.config:
  enabled: true
  allowedHeaders: ['*']
  allowedMethods: []
  allowedOrigins: ['https://frontend.example.com']
  exposedHeaders: false
  maxAge: false
  supportsCredentials: false

Timelines

Simple View with exposed filters via UI + config export: half day. Custom plugin (row, filter, sort), custom data table, REST export: 2–3 days.