Весьма распространённый случай, когда в качестве exposed filter используется поле, связанное с таксономией. Так вы получаете набор опций в фильтре для своего представления, которое доступно пользователю.
Также весьма часто некоторые дополнительные условия выборки ограничивают набор данных так, что часть опций фильтра становится не нужной, так как их выбор приводит к пустому результату.
Т.е. опция в фильтре есть, а список будет пустой при её выборе. Это довольно не приятный опыт для пользователя, и нам его стоит избегать.
Решения для пустых категорий
Используется традиционно два пути, чтобы как то решить ситуацию, причем один из них простой, но тупиковый — представление настраивается так, чтобы красиво оформить список в случае, если результаты запроса пусты. Выводится сообщение об отсутствии результата, стильная картинка и ссылки на другие страницы каталога, часто даже без учета контекста запроса.
Это действительно сглаживает негативное впечатление пользователя, т.к. дизайн страницы выглядит хоть и бесполезным, но целостным. Принципиально же проблема не разрешается.
Поэтому рассмотрим другой путь, а именно уберем из фильтра категории, которые не содержат результатов.
Я буду показывать в контексте своей задачи, вам придется подумать, как это можно применить для вашего случая.
Потребуется реализация hook_form_views_exposed_form_alter и работа с базой данных, т.к. другого способа выяснить будет ли запрос пуст, кроме как его выполнить предварительно, не существует.
Детали задачи
Моё представление создавало список сущностей commerce_product_variation в контексте выбранного тега товара. А на форме был фильтр по категории товара. Получалось, что для выбранного тега товара, не все категории были актуальны. Нужно было удалить из фильтра лишние (пустые) категории.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 |
/** * Implements hook_form_views_exposed_form_alter(). */ function MODULENAME_form_views_exposed_form_alter(&$form, FormStateInterface $form_state, string $form_id) { if ($form['#id'] == 'views-exposed-form-goods-by-tags-block-1') { if (array_key_exists('categ', $form)) { // поле фильтра с категориями называлось categ $options = &$form['categ']['#options']; // контекст таксономии тегов извлечем из маршрута // (список показывается на странице конкретного тега) $term_id = \Drupal::routeMatch()->getRawParameter('taxonomy_term'); $query = \Drupal::database()->select('commerce_product_variation_field_data', 'v'); $query->join('commerce_product__field_categ', 'c', 'v.product_id = c.entity_id'); $query->join( 'commerce_product__field_tags', 't', 'v.product_id = t.entity_id AND t.field_tags_target_id = ' . intval($term_id)); // выбираем значения категорий $query->addField('c', 'field_categ_target_id'); // интересуют только опубликованные вариации $query->condition('v.status', NodeInterface::PUBLISHED); $results = $query->distinct()->execute()->fetchCol(); // получив список категорий, отфильтруем набор категорий в представлении foreach ($options as $key => $value) { if (!in_array($key, $results) && $key !== 'All') { unset($options[$key]); } } } } } |
Вероятно структура кода hook будет у вас такой же, только потребуется сконструировать собственный запрос к базе.