Drupal 8 + Commerce + Taxonomy + Каталог

Главные вкладки

Аватар пользователя YakovKN YakovKN 30 мая 2019 в 21:13

Всем привет!
Подскажите пожалуйста со свежими мыслями,
Как сделать чтобы в каталоге где есть термины таксономии:

Категория 1
-Подкатегория1
-Подкатегория2
-Подкатегория3
Категория 2
-Подкатегория21
-Подкатегория22
-Подкатегория23

Сейчас при нажатии на Категория1 выводит:
-Подкатегория1
-Подкатегория2
-Подкатегория3
При нажатии на одну них выводит товар который в этой категории.

А нужно чтобы при нажатии на Категория1 выводил все подкатегории вместе в товаром который находится в этих подкатегориях.

Заранее благодарю за ответ.

Комментарии

Аватар пользователя YakovKN YakovKN 31 мая 2019 в 9:29

Доброе УТРО!
в 7ке достаточно было у Content: Has taxonomy term ID (with depth) поставить глубину 2 и убрать второй фильтр и все работало как надо.
В 8 нет такого фильтра. Все что нашел не работает.

Semantics wrote:
Используйте для аргументов термины с дочерними.
Сложность в чём? Что вы уже сделали?

Сейчас сделан каталог через views который выводит все по словарю каталог, следующий views выдает при нажатии на категорию1 подкатегория1/подкатегория2/подкатегория3 и следующий views выводит сам товар в категориях.
Где настроить эти термины с дочерними?

Аватар пользователя gun_dose gun_dose 31 мая 2019 в 9:54

Проблема в том, что контекстный фильтр "имеет термин таксономии с глубиной" работает только для нод, а продукт - это не нода.

Собственно, вот код стандартного хэндлера:
https://git.drupalcode.org/project/drupal/blob/8.7.x/core/modules/taxono...

Можно скопировать в свой кастомный модуль, поменять название класса, айдишник плагина, и само собой переделать метод query, там выборка должна идти не из taxonomy_index, а из таблицы, в которой хранится конкретно ваше поле

Аватар пользователя mamatuik mamatuik 31 мая 2019 в 13:07

Думаю, этот код обработчика автору темы не поможет.

А любой материал в друпал является узлом со своим идентификатором (node with id)
Поэтому чётко убеждён, что с помощью видов можно аккуратненько решить все вопросы + ну и плюс модули таксономии из общеоткрытого набора.

Но автор до сих пор не постучался ко мне за помощью, значит, будет сам пытаться. И то верно... штуку сбережёт, - на пивко да сигареты хватит (могу предположить)

И для gun_dose лично: я ещё раз подчёркиваю, что на главной странице ранее мной упомянутого сайта в разделе "НОВОЕ на Форуме" реализована совершенно нетривиальная вещь с вызовом таксономии.
Ранее я не встречал, чтоб комментарии выдавались с такой детализацией.
Может я ошибаюсь, а?

По drupal 8 - до сих пор не вижу смысла затачивать сайты под неё ввиду нестабильности.
Наоборот, нужно привыкать к новому коду да и плюсом может служить, пожалуй, то, что встроен opcache - для пользователей, кто не хочет переживать о хранилищах.
Что там ещё? - .yaml есть

Аватар пользователя gun_dose gun_dose 31 мая 2019 в 13:37
2

Совершенно точно говорю, что в восьмёрке товары - это не ноды. И вообще, зачем вы путаете человека, если ни разу не работали с восьмёркой?

Аватар пользователя YakovKN YakovKN 3 июня 2019 в 1:00

Добрый вечер!
Почему то выдает что "Обработчик испорчен или отсутствует"...
Сам код нашел вот такой:


<?php

namespace Drupal\commerce_ext\Plugin\views\filter;

use 

Drupal\Core\Form\FormStateInterface;
use 
Drupal\taxonomy\Plugin\views\filter\TaxonomyIndexTid;

/**
 * Filter handler for taxonomy terms with depth.
 *
 * This handler is actually part of the node table and has some restrictions,
 * because it uses a subquery to find nodes with.
 *
 * @ingroup views_filter_handlers
 *
 * @ViewsFilter("commerce_product_taxonomy_index_tid_depth")
 */
class CommerceProductTaxonomyIndexTidDepth extends TaxonomyIndexTid {

  public function 

operatorOptions($which 'title') {
    return array(
      
'or' => $this->t('Is one of'),
    );
  }

  protected function 

defineOptions() {
    
$options parent::defineOptions();

    

$options['depth'] = array('default' => 0);

    return 

$options;
  }

  public function 

buildExtraOptionsForm(&$formFormStateInterface $form_state) {
    
parent::buildExtraOptionsForm($form$form_state);

    

$form['depth'] = array(
      
'#type' => 'weight',
      
'#title' => $this->t('Depth'),
      
'#default_value' => $this->options['depth'],
      
'#description' => $this->t('The depth will match nodes tagged with terms in the hierarchy. For example, if you have the term "fruit" and a child term "apple", with a depth of 1 (or higher) then filtering for the term "fruit" will get nodes that are tagged with "apple" as well as "fruit". If negative, the reverse is true; searching for "apple" will also pick up nodes tagged with "fruit" if depth is -1 (or lower).'),
    );
  }

  public function 

query() {
    
// If no filter values are present, then do nothing.
    
if (count($this->value) == 0) {
      return;
    }
    elseif (
count($this->value) == 1) {
      
// Sometimes $this->value is an array with a single element so convert it.
      
if (is_array($this->value)) {
        
$this->value current($this->value);
      }
      
$operator '=';
    }
    else {
      
$operator 'IN';# " IN (" . implode(', ', array_fill(0, sizeof($this->value), '%d')) . ")";
    
}

    

// The normal use of ensureMyTable() here breaks Views.
    // So instead we trick the filter into using the alias of the base table.
    //   See https://www.drupal.org/node/271833.
    // If a relationship is set, we must use the alias it provides.
    
if (!empty($this->relationship)) {
      
$this->tableAlias $this->relationship;
    }
    
// If no relationship, then use the alias of the base table.
    
else {
      
$this->tableAlias $this->query->ensureTable($this->view->storage->get('base_table'));
    }

    

// Now build the subqueries.
    
$subquery db_select('taxonomy_index_commerce_product''tn');
    
$subquery->addField('tn''product_id');
    
$where db_or()->condition('tn.tid'$this->value$operator);
    
$last "tn";

    if (

$this->options['depth'] > 0) {
      
$subquery->leftJoin('taxonomy_term_hierarchy''th'"th.tid = tn.tid");
      
$last "th";
      foreach (
range(1abs($this->options['depth'])) as $count) {
        
$subquery->leftJoin('taxonomy_term_hierarchy'"th$count""$last.parent = th$count.tid");
        
$where->condition("th$count.tid"$this->value$operator);
        
$last "th$count";
      }
    }
    elseif (
$this->options['depth'] < 0) {
      foreach (
range(1abs($this->options['depth'])) as $count) {
        
$subquery->leftJoin('taxonomy_term_hierarchy'"th$count""$last.tid = th$count.parent");
        
$where->condition("th$count.tid"$this->value$operator);
        
$last "th$count";
      }
    }

    

$subquery->condition($where);
    
$this->query->addWhere($this->options['group'], "$this->tableAlias.$this->realField"$subquery'IN');
  }

}

?>
Аватар пользователя gun_dose gun_dose 3 июня 2019 в 6:40

В журнале должна быть ошибка. Но я вижу, что у вас используется таблица taxonomy_index_commerce_product. Я на 99% уверен, что она не существует. У вас название таблицы должно быть product__название_поля_с_таксономией.

Аватар пользователя YakovKN YakovKN 3 июня 2019 в 20:58

gun_dose wrote:
В журнале должна быть ошибка. Но я вижу, что у вас используется таблица taxonomy_index_commerce_product. Я на 99% уверен, что она не существует. У вас название таблицы должно быть product__название_поля_с_таксономией.

В логах пишет Warning: Invalid argument, таблица taxonomy_index_commerce_product есть.
Сейчас пробовал таблицу "commerce_product__field_catalog", но пишет ту же ошибку.
php c версии 7.3 переключал на 7.2 и 7.1 до этого. Может попробовать на чистом друпале все поставить...

Аватар пользователя YakovKN YakovKN 3 июня 2019 в 23:36

В логах сервера есть "/admin/structure/views/ajax/handler/catalog2/default/argument/term_commerce_product_tid_depth".
В логах сайта большая портянка начинающаяся с "Warning: Invalid argument supplied for foreach() в"

Аватар пользователя gun_dose gun_dose 4 июня 2019 в 6:34

Вы понимаете, что в тексте этой ошибки конкретно указано, в какой конкретно строке кода что пошло не так? Вот эту всю портянку давайте сюда.

Аватар пользователя YakovKN YakovKN 4 июня 2019 в 7:29

Warning: Invalid argument supplied for foreach() в template_preprocess_item_list() (строка 1095 из /urlserver/core/includes/theme.inc) #0 /urlserver/core/includes/bootstrap.inc(584): _drupal_error_handler_real(2, 'Invalid argumen...', '//urluser...', 1095, Array) #1 /urlserver/core/includes/theme.inc(1095): _drupal_error_handler(2, 'Invalid argumen...', '//urluser...', 1095, Array) #2 /urlserver/core/lib/Drupal/Core/Theme/ThemeManager.php(287): template_preprocess_item_list(Array, 'item_list', Array) #3 /urlserver/core/lib/Drupal/Core/Render/Renderer.php(437): Drupal\Core\Theme\ThemeManager->render('item_list', Array) #4 /urlserver/core/lib/Drupal/Core/Render/Renderer.php(450): Drupal\Core\Render\Renderer->doRender(Array) #5 /urlserver/core/lib/Drupal/Core/Render/Renderer.php(450): Drupal\Core\Render\Renderer->doRender(Array) #6 /urlserver/core/lib/Drupal/Core/Render/Renderer.php(450): Drupal\Core\Render\Renderer->doRender(Array) #7 /urlserver/core/lib/Drupal/Core/Render/Renderer.php(195): Drupal\Core\Render\Renderer->doRender(Array, true) #8 /urlserver/core/lib/Drupal/Core/Render/Renderer.php(139): Drupal\Core\Render\Renderer->render(Array, true) #9 /urlserver/core/lib/Drupal/Core/Render/Renderer.php(582): Drupal\Core\Render\Renderer->Drupal\Core\Render\{closure}() #10 /urlserver/core/lib/Drupal/Core/Render/Renderer.php(140): Drupal\Core\Render\Renderer->executeInRenderContext(Object(Drupal\Core\Render\RenderContext), Object(Closure)) #11 /urlserver/core/modules/views_ui/src/Form/Ajax/ViewsFormBase.php(223): Drupal\Core\Render\Renderer->renderRoot(Array) #12 /urlserver/core/modules/views_ui/src/Form/Ajax/ViewsFormBase.php(149): Drupal\views_ui\Form\Ajax\ViewsFormBase->ajaxFormWrapper('Drupal\\views_ui...', Object(Drupal\Core\Form\FormState)) #13 /urlserver/core/modules/views_ui/src/Form/Ajax/AddHandler.php(36): Drupal\views_ui\Form\Ajax\ViewsFormBase->getForm(Object(Drupal\views_ui\ViewUI), 'default', 'ajax') #14 [internal function]: Drupal\views_ui\Form\Ajax\AddHandler->getForm(Object(Drupal\views_ui\ViewUI), 'default', 'ajax', 'argument') #15 /urlserver/core/lib/Drupal/Core/EventSubscriber/EarlyRenderingControllerWrapperSubscriber.php(123): call_user_func_array(Array, Array) #16 /urlserver/core/lib/Drupal/Core/Render/Renderer.php(582): Drupal\Core\EventSubscriber\EarlyRenderingControllerWrapperSubscriber->Drupal\Core\EventSubscriber\{closure}() #17 /urlserver/core/lib/Drupal/Core/EventSubscriber/EarlyRenderingControllerWrapperSubscriber.php(124): Drupal\Core\Render\Renderer->executeInRenderContext(Object(Drupal\Core\Render\RenderContext), Object(Closure)) #18 /urlserver/core/lib/Drupal/Core/EventSubscriber/EarlyRenderingControllerWrapperSubscriber.php(97): Drupal\Core\EventSubscriber\EarlyRenderingControllerWrapperSubscriber->wrapControllerExecutionInRenderContext(Array, Array) #19 /urlserver/vendor/symfony/http-kernel/HttpKernel.php(151): Drupal\Core\EventSubscriber\EarlyRenderingControllerWrapperSubscriber->Drupal\Core\EventSubscriber\{closure}() #20 /urlserver/vendor/symfony/http-kernel/HttpKernel.php(68): Symfony\Component\HttpKernel\HttpKernel->handleRaw(Object(Symfony\Component\HttpFoundation\Request), 1) #21 /urlserver/core/lib/Drupal/Core/StackMiddleware/Session.php(57): Symfony\Component\HttpKernel\HttpKernel->handle(Object(Symfony\Component\HttpFoundation\Request), 1, true) #22 /urlserver/core/lib/Drupal/Core/StackMiddleware/KernelPreHandle.php(47): Drupal\Core\StackMiddleware\Session->handle(Object(Symfony\Component\HttpFoundation\Request), 1, true) #23 /urlserver/core/modules/page_cache/src/StackMiddleware/PageCache.php(99): Drupal\Core\StackMiddleware\KernelPreHandle->handle(Object(Symfony\Component\HttpFoundation\Request), 1, true) #24 /urlserver/core/modules/page_cache/src/StackMiddleware/PageCache.php(78): Drupal\page_cache\StackMiddleware\PageCache->pass(Object(Symfony\Component\HttpFoundation\Request), 1, true) #25 /urlserver/core/lib/Drupal/Core/StackMiddleware/ReverseProxyMiddleware.php(47): Drupal\page_cache\StackMiddleware\PageCache->handle(Object(Symfony\Component\HttpFoundation\Request), 1, true) #26 /urlserver/core/lib/Drupal/Core/StackMiddleware/NegotiationMiddleware.php(52): Drupal\Core\StackMiddleware\ReverseProxyMiddleware->handle(Object(Symfony\Component\HttpFoundation\Request), 1, true) #27 /urlserver/vendor/stack/builder/src/Stack/StackedHttpKernel.php(23): Drupal\Core\StackMiddleware\NegotiationMiddleware->handle(Object(Symfony\Component\HttpFoundation\Request), 1, true) #28 /urlserver/core/lib/Drupal/Core/DrupalKernel.php(693): Stack\StackedHttpKernel->handle(Object(Symfony\Component\HttpFoundation\Request), 1, true) #29 /urlserver/index.php(19): Drupal\Core\DrupalKernel->handle(Object(Symfony\Component\HttpFoundation\Request)) #30 {main}.
и второй лог
Warning: Invalid argument supplied for foreach() в Drupal\views\Plugin\views\argument\Broken->buildOptionsForm() (строка 56 из /urlserver/core/modules/views/src/Plugin/views/BrokenHandlerTrait.php) #0 /urlserver/core/includes/bootstrap.inc(584): _drupal_error_handler_real(2, 'Invalid argumen...', '//urluser...', 56, Array) #1 /urlserver/core/modules/views/src/Plugin/views/BrokenHandlerTrait.php(56): _drupal_error_handler(2, 'Invalid argumen...', '//urluser...', 56, Array) #2 /urlserver/core/modules/views_ui/src/Form/Ajax/ConfigHandler.php(167): Drupal\views\Plugin\views\argument\Broken->buildOptionsForm(Array, Object(Drupal\Core\Form\FormState)) #3 [internal function]: Drupal\views_ui\Form\Ajax\ConfigHandler->buildForm(Array, Object(Drupal\Core\Form\FormState)) #4 /urlserver/core/lib/Drupal/Core/Form/FormBuilder.php(518): call_user_func_array(Array, Array) #5 /urlserver/core/lib/Drupal/Core/Form/FormBuilder.php(275): Drupal\Core\Form\FormBuilder->retrieveForm('views_ui_config...', Object(Drupal\Core\Form\FormState)) #6 /urlserver/core/modules/views_ui/src/Form/Ajax/ViewsFormBase.php(214): Drupal\Core\Form\FormBuilder->buildForm('views_ui_config...', Object(Drupal\Core\Form\FormState)) #7 /urlserver/core/lib/Drupal/Core/Render/Renderer.php(582): Drupal\views_ui\Form\Ajax\ViewsFormBase->Drupal\views_ui\Form\Ajax\{closure}() #8 /urlserver/core/modules/views_ui/src/Form/Ajax/ViewsFormBase.php(216): Drupal\Core\Render\Renderer->executeInRenderContext(Object(Drupal\Core\Render\RenderContext), Object(Closure)) #9 /urlserver/core/modules/views_ui/src/Form/Ajax/ViewsFormBase.php(149): Drupal\views_ui\Form\Ajax\ViewsFormBase->ajaxFormWrapper('Drupal\\views_ui...', Object(Drupal\Core\Form\FormState)) #10 /urlserver/core/modules/views_ui/src/Form/Ajax/AddHandler.php(36): Drupal\views_ui\Form\Ajax\ViewsFormBase->getForm(Object(Drupal\views_ui\ViewUI), 'default', 'ajax') #11 [internal function]: Drupal\views_ui\Form\Ajax\AddHandler->getForm(Object(Drupal\views_ui\ViewUI), 'default', 'ajax', 'argument') #12 /urlserver/core/lib/Drupal/Core/EventSubscriber/EarlyRenderingControllerWrapperSubscriber.php(123): call_user_func_array(Array, Array) #13 /urlserver/core/lib/Drupal/Core/Render/Renderer.php(582): Drupal\Core\EventSubscriber\EarlyRenderingControllerWrapperSubscriber->Drupal\Core\EventSubscriber\{closure}() #14 /urlserver/core/lib/Drupal/Core/EventSubscriber/EarlyRenderingControllerWrapperSubscriber.php(124): Drupal\Core\Render\Renderer->executeInRenderContext(Object(Drupal\Core\Render\RenderContext), Object(Closure)) #15 /urlserver/core/lib/Drupal/Core/EventSubscriber/EarlyRenderingControllerWrapperSubscriber.php(97): Drupal\Core\EventSubscriber\EarlyRenderingControllerWrapperSubscriber->wrapControllerExecutionInRenderContext(Array, Array) #16 /urlserver/vendor/symfony/http-kernel/HttpKernel.php(151): Drupal\Core\EventSubscriber\EarlyRenderingControllerWrapperSubscriber->Drupal\Core\EventSubscriber\{closure}() #17 /urlserver/vendor/symfony/http-kernel/HttpKernel.php(68): Symfony\Component\HttpKernel\HttpKernel->handleRaw(Object(Symfony\Component\HttpFoundation\Request), 1) #18 /urlserver/core/lib/Drupal/Core/StackMiddleware/Session.php(57): Symfony\Component\HttpKernel\HttpKernel->handle(Object(Symfony\Component\HttpFoundation\Request), 1, true) #19 /urlserver/core/lib/Drupal/Core/StackMiddleware/KernelPreHandle.php(47): Drupal\Core\StackMiddleware\Session->handle(Object(Symfony\Component\HttpFoundation\Request), 1, true) #20 /urlserver/core/modules/page_cache/src/StackMiddleware/PageCache.php(99): Drupal\Core\StackMiddleware\KernelPreHandle->handle(Object(Symfony\Component\HttpFoundation\Request), 1, true) #21 /urlserver/core/modules/page_cache/src/StackMiddleware/PageCache.php(78): Drupal\page_cache\StackMiddleware\PageCache->pass(Object(Symfony\Component\HttpFoundation\Request), 1, true) #22 /urlserver/core/lib/Drupal/Core/StackMiddleware/ReverseProxyMiddleware.php(47): Drupal\page_cache\StackMiddleware\PageCache->handle(Object(Symfony\Component\HttpFoundation\Request), 1, true) #23 /urlserver/core/lib/Drupal/Core/StackMiddleware/NegotiationMiddleware.php(52): Drupal\Core\StackMiddleware\ReverseProxyMiddleware->handle(Object(Symfony\Component\HttpFoundation\Request), 1, true) #24 /urlserver/vendor/stack/builder/src/Stack/StackedHttpKernel.php(23): Drupal\Core\StackMiddleware\NegotiationMiddleware->handle(Object(Symfony\Component\HttpFoundation\Request), 1, true) #25 /urlserver/core/lib/Drupal/Core/DrupalKernel.php(693): Stack\StackedHttpKernel->handle(Object(Symfony\Component\HttpFoundation\Request), 1, true) #26 /urlserver/index.php(19): Drupal\Core\DrupalKernel->handle(Object(Symfony\Component\HttpFoundation\Request)) #27 {main}.

Аватар пользователя YakovKN YakovKN 4 июня 2019 в 20:44

8.6.16
сейчас taxonomy_term_hierarchy нет..., но была и до этого ошибка тоже была "Обработчик испорчен или отсутствует". При обновлении с 8.5 может что то затерлось с базой.
Пробовал менять на taxonomy_term__parent результат тот же.

Аватар пользователя gun_dose gun_dose 4 июня 2019 в 22:56

Ну во-первых абсолютно точно taxonomy_term__parent должен быть вместо taxonomy_term_hierarchy. Во-вторых, надо проверять, всё ли правильно там с колонками в методе query. По-хорошему, нужно смотреть через xdebug. Но если для вас это сильно сложно, то можно в методе query вставить строку, которая пишет что-нибудь в журнал. Просто любое сообщение, типа 'привет'. И по журналу смотреть, срабатывает ли эта строка. Перемещая её ниже по коду, можно найти ту самую строку, после которой этот код не вызовется, тогда будет понятно, что с этим делать.

В двух словах "обработчик испорчен или отсутствует" - это так называемый BrokenHandler. Когда в хэндлерах (фильтрах, полях, аргументах и т.д.) происходит критическая ошибка, то вызывается этот хэндлер, как заглушка.