Facet Views 404 in Drupal 9

Today we will have a small module for Drupal 9, which helped partially solve the following problem:

There is a page of facet search, with a conventional way website.com/catalog, also on the site there are notes of a product type that has a url like website.com/catalog/productname23. As we can see, they have a common part, which is why when we delete the product and transition to it we have a page instead of 404 code facet search with 200 code. 

When I was looking for a solution to this problem, I found a module Views404, but unfortunately it supports only the Drupal of the 7th version, so I decided to do something quickly to work.

The general principle of operation of our module will be as follows - first we check whether we are on a page with URL which coincides with us. The following is a check whether an open page of the node, if we deleted our product, then this check should work successfully. After that, we get a list of all facet field of the products, to obtain names of url alias of facets. After that, we know how we have alias facets, we check that there are in our address. If not - a 404 page redirect.

First create info.yml file

name: Views404 v9
description: 'Fix 404 for Views in Drupal 9'
type: module
version: 1.0
core_version_requirement: ^9 || ^10
package: DARTHARTH
dependencies:
  - drupal:views

then, create .module file

<?php

use Drupal\Core\Routing\RouteMatchInterface;
use Symfony\Component\HttpFoundation\RedirectResponse;
use Drupal\Core\Database\Database;

function getFacetAliases() {
  $connection = Database::getConnection();
  $like = $connection->escapeLike('search_api_db_facet_field_') . '%';
  $query = $connection->query("SHOW TABLE STATUS LIKE :like", [':like' => $like]);
  $tables = $query->fetchAllKeyed(0, 0);

  $facet_aliases = [];
  foreach ($tables as $table_name => $data) {
      if ($table_name !== 'search_api_db_facet_field_type') {
          $alias = str_replace('search_api_db_facet_field_', '', $table_name);
          $facet_aliases[] = $alias;
      }
  }

  return $facet_aliases;
}

/**
 * Implements hook_preprocess_page().
 */
function darth_views404_preprocess_page(&$variables) {
    $current_path = \Drupal::service('path.current')->getPath();
    $route_match = \Drupal::routeMatch();

    if (strpos($current_path, '/catalog/') !== FALSE) {
        if (isNodePage($route_match)) {
            return;
        }

        $facet_aliases = getFacetAliases();

        $path_parts = explode('/', trim($current_path, '/'));

        $facet_in_url = false;
        foreach ($facet_aliases as $alias) {
            if (in_array($alias, $path_parts)) {
                $facet_in_url = true;
                break;
            }
        }

        if (!$facet_in_url) {
          redirectTo404();
        }
    }
}

/**
 * 
 *
 * @param RouteMatchInterface $route_match
 * @return bool
 */
function isNodePage(RouteMatchInterface $route_match) {
    if ($route_match->getRouteName() == 'entity.node.canonical') {
        return TRUE;
    }

    return FALSE;
}

/**
 * 
 */
function redirectTo404() {
    $response = new RedirectResponse('/404', 301);
    $response->send();
    exit;
}

Link to GitHub

Plain text

  • No HTML tags allowed.
  • Lines and paragraphs break automatically.
  • Web page addresses and email addresses turn into links automatically.
The comment language code.