
In this article, I will explain how I created the book_navigation_remover module for Drupal 7. I will describe what Drupal 7 is, the role of the Book module, and why simply hiding the book navigation using CSS is not sufficient. I will then provide detailed, step-by-step instructions on how you can build your own module to disable the book navigation. Finally, I will offer guidance on adapting the concept for Drupal 9, 10, and 11, including file names, commented code, and options for further customization.
What Is Drupal 7?
Drupal 7 is an open-source content management system (CMS) that many organizations and developers use to build robust and flexible websites. Drupal 7 is known for its modular architecture, which allows you to extend the functionality of your website by installing custom or contributed modules.
What Is the Book Module?
The Book module is a core module in Drupal that enables you to create, organize, and navigate collections of related content, similar to chapters in a book. The module automatically generates a navigation menu, known as the book navigation, to help users move between sections. However, some website administrators choose to hide the navigation with CSS. Although this method visually removes the menu, the underlying HTML is still present, which is not ideal.
Why Not Just Hide the Navigation with CSS?
Hiding the book navigation using CSS (for example, by setting display: none;
) is a common practice. However, this approach has several drawbacks:
- Performance Impact: The hidden markup is still loaded and delivered to the user, which can affect performance.
- Accessibility Concerns: Assistive technologies such as screen readers may still detect the hidden elements.
- Maintenance Challenges: Future developers may be confused by hidden elements that appear to serve no purpose.
In my module, I want to disable the book navigation entirely. Using a module to disable the output is a cleaner solution that improves performance, enhances accessibility, and maintains clean markup.
Creating the book_navigation_remover Module for Drupal 7
Below are the steps I followed to create my module, which disables the book navigation in Drupal 7.
Step 1: Create the Module Folder
Create a folder named book_navigation_remover inside your Drupal 7 modules directory. This is typically located at sites/all/modules/custom
.
Step 2: Create the .info File
Inside the book_navigation_remover folder, create a file named book_navigation_remover.info with the following content:
; book_navigation_remover.info
name = Book Navigation Remover
description = "Disables the book navigation menu from the site output."
core = 7.x
package = Custom
The comments, which begin with a semicolon, provide information about the module. This file tells Drupal basic details about your module.
Step 3: Create the .module File
Next, create a file named book_navigation_remover.module in the same folder. This file contains the PHP code that disables the book navigation:
<?php
/** * @file * Module file for Book Navigation Remover. */
/** * Implements hook_menu_alter(). * * In my module, I want to disable the book navigation by removing the menu callback. */
function book_navigation_remover_menu_alter(&$items) { // Check if the book navigation menu item exists. if (isset($items['book'])) { // Remove the book navigation menu item to prevent it from rendering. unset($items['book']); }
}
/** * Alternatively, you may implement hook_preprocess_page() to remove the variable. * Uncomment the following code if you prefer this approach. */
// function book_navigation_remover_preprocess_page(&$variables) {
// if (isset($variables['book_navigation'])) {
// $variables['book_navigation'] = '';
// }
// }
?>
The code uses Drupal hooks to alter the default behavior of the Book module. In my module, I want to disable the book navigation by unsetting the menu item that generates it. An alternative approach using hook_preprocess_page() is provided in comments.
Step 4: Enable the Module
Go to Administration > Modules on your Drupal 7 site. Locate "Book Navigation Remover" under the Custom category and enable it. Do not forget to clear the cache so that Drupal can register the changes.
Adapting the Concept for Drupal 9, 10, and 11
While Drupal 7 modules are written in procedural PHP, Drupal 8 and later versions use an object-oriented approach. The overall concept remains the same: you want to disable the book navigation output, but the file structure and code style differ.
File Structure for Drupal 9/10/11
For Drupal 9, 10, or 11, create a folder named book_navigation_remover in your custom modules directory (typically /modules/custom/book_navigation_remover
). Inside this folder, create the following files:
- book_navigation_remover.info.yml
- src/EventSubscriber/RemoveBookNavigationSubscriber.php
- (Optionally) a book_navigation_remover.module file if procedural hooks are required.
Example: book_navigation_remover.info.yml
# book_navigation_remover.info.yml
name: Book Navigation Remover
type: module
description: 'Disables the book navigation menu from the site output.'
core_version_requirement: ^9 || ^10 || ^11
package: Custom
Example: Using an Event Subscriber
In Drupal 8 and later, you can use an event subscriber to alter render arrays. Create a file named RemoveBookNavigationSubscriber.php in the src/EventSubscriber/ folder with the following code:
<?php
namespace Drupal\book_navigation_remover\EventSubscriber;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Drupal\Core\Render\PageDisplayVariantSubscriber;
use Symfony\Component\HttpKernel\Event\ViewEvent;
use Symfony\Component\HttpKernel\KernelEvents;
/** * Class RemoveBookNavigationSubscriber. * * Removes the book navigation from the page render array. */
class RemoveBookNavigationSubscriber implements EventSubscriberInterface { /** * {@inheritdoc} */ public static function getSubscribedEvents() { // Subscribe to the kernel view event with higher priority than page_display. $events[KernelEvents::VIEW][] = ['onView', PageDisplayVariantSubscriber::PRIORITY + 10]; return $events; } /** * Alters the page render array to remove book navigation. * * @param \Symfony\Component\HttpKernel\Event\ViewEvent $event * The event object. */ public function onView(ViewEvent $event) { $result = $event->getControllerResult(); // Only act on render arrays if (is_array($result)) { // Remove book navigation if present if (isset($result['book_navigation'])) { unset($result['book_navigation']); $event->setControllerResult($result); } // Also check for book navigation in content if (isset($result['content']['book_navigation'])) { unset($result['content']['book_navigation']); $event->setControllerResult($result); } } }
}
Declaring the Service
For Drupal 9/10/11, you must declare the event subscriber in a book_navigation_remover.services.yml file:
# book_navigation_remover.services.yml
services: book_navigation_remover.remove_subscriber: class: Drupal\book_navigation_remover\EventSubscriber\RemoveBookNavigationSubscriber tags: - { name: event_subscriber }
Additional Enhancements and Customization
You can further enhance your module with additional features:
Configuration Options
Create a configuration form to make the module more flexible:
<?php
// book_navigation_remover.module for Drupal 9/10/11
/** * Implements hook_form_FORM_ID_alter(). */
function book_navigation_remover_form_book_admin_settings_alter(&$form, \Drupal\Core\Form\FormStateInterface $form_state, $form_id) { $config = \Drupal::config('book_navigation_remover.settings'); $form['book_navigation_remover'] = [ '#type' => 'details', '#title' => t('Book Navigation Removal Settings'), '#open' => TRUE, ]; $form['book_navigation_remover']['remove_all'] = [ '#type' => 'checkbox', '#title' => t('Remove book navigation from all pages'), '#default_value' => $config->get('remove_all') ?: TRUE, '#description' => t('If checked, book navigation will be removed from all pages. Otherwise, use the content type settings below.'), ]; $form['book_navigation_remover']['content_types'] = [ '#type' => 'checkboxes', '#title' => t('Content types'), '#description' => t('Select content types to remove book navigation from.'), '#options' => node_type_get_names(), '#default_value' => $config->get('content_types') ?: [], '#states' => [ 'visible' => [ ':input[name="remove_all"]' => ['checked' => FALSE], ], ], ]; $form['#submit'][] = 'book_navigation_remover_settings_submit';
}
/** * Submit handler for book settings form. */
function book_navigation_remover_settings_submit($form, \Drupal\Core\Form\FormStateInterface $form_state) { $config = \Drupal::configFactory()->getEditable('book_navigation_remover.settings'); $config->set('remove_all', $form_state->getValue('remove_all')) ->set('content_types', $form_state->getValue('content_types')) ->save();
}
?>
Secure and Streamlined Navigation for Your Drupal Site
The dedicated module approach to remove book navigation offers significant advantages over CSS-based solutions. This method delivers numerous benefits to your website:
- Enhanced Performance: Your pages will load faster because unnecessary markup isn't being delivered to the client.
- Improved Accessibility: Screen readers and other assistive technologies won't be confused by hidden but present navigation elements.
- Clean Codebase: Future developers working on your site will find a cleaner, more maintainable codebase without hidden elements.
- Best Practices: This approach aligns with Drupal's development best practices and architectural principles.
The modular nature of this solution allows you to easily enable or disable the functionality as needed, giving you complete control over your site's navigation structure. Whether you're working with Drupal 7 or the more modern Drupal 9, 10, or 11, these principles apply across all versions.
The time invested in creating a proper module rather than applying quick CSS fixes results in a more robust foundation for your site that will serve you well as your project evolves. The code samples provided are ready for immediate implementation, and the customization options allow you to tailor the solution to your specific requirements.
Happy coding, and may your Drupal projects flourish with clean, efficient navigation!