Pass arguments to the contextual filter of a view
In web development we often encounter situations and challenges that require versatile and customized solutions for a specific use case.
Views in Drupal are a powerful tool that allows you to generate lists intuitively from the administration interface, without requiring much knowledge of MySQL or any relational database language. Contextual filters are an additional way to classic filters that allow you to configure a view, since they are filters that, as the word indicates, come from a different context, such as the url.
The problem: displaying information from different entities in a view
Imagine you are building a Drupal website that includes an e-commerce system using Drupal Commerce 2. One of the pages you need to create is a table that displays detailed information about the products and order items associated with a specific request. However, a problem arises: when displaying the description (body) of a product, the other fields such as the unit price (Unit price) and the total price (Total price) show the default currency (β¬), regardless of the method of payment that has been used.
This occurs because it is not possible to relate both entities directly from the view. Now let's get to the solution.
Modify arguments for a view's contextual filter
To solve this problem, we need a way to pass additional information to the view's contextual filter, so that we can dynamically adjust the behavior of the fields based on the information specific to each order. Fortunately, in Drupal we have hooks that allow us to intervene in the view construction process and make modifications according to our needs.
The code shown below is an example of how we can use the hook hook_views_pre_view() to add an additional argument to a view's contextual filter:
/**
* Implements hook_views_pre_view().
*/
function MODULE_views_pre_view(ViewExecutable $view, $display_id, array &$args) {
if ($view->id() == 'commerce_order_item_table') {
$order = Order::load($args[0]); // Get order object.
$currency = $order->getTotalPrice()->getCurrencyCode(); // Get order currency code.
$args[] = $currency; // Add currency to contextual filter arguments.
}
}This code is executed before the commerce_order_item_table view is rendered. What it does is load the order object (Order) corresponding to the ID of the order passed as an argument to the contextual filter. It then gets the currency associated with the order and adds it as an additional argument to the view's contextual filter.
Conclusion
Modifying arguments for a view's contextual filter in Drupal is a powerful technique that allows us to dynamically adapt the behavior of our views based on the specific needs of our website. In the example we have seen, we were able to solve an issue related to displaying Commerce entity information by adjusting the contextual filter to take into account the currency associated with each order. With a solid understanding of the hooks available in Drupal and a little creativity, we can overcome any obstacle that arises in the development of our projects.