地区の語彙があり、以下のようなネストされた分類用語があります。
Drupal 8に分類用語のビューがあります。Drupal$ === 8は、親と子を含むすべての用語のフィルターを公開しています。用語の親のコンテキストフィルターを追加すると、exposed filterは、コンテキストフィルターの親用語と一致する子用語のみを表示する必要があります。
たとえば、URLにDeogharが含まれている場合、公開されたフィルター(フィルターの下など)にはオプションとしてKaronという用語のみが表示されます。
私は最近、MYMODULE_form_views_exposed_form_alter
を使用した私のプロジェクトでこれを行いました。このコードは、コンテキストフィルターとして最初の位置に用語IDを持つビューがあることを前提としています。 domain.com/myview/123
<?php
function MYMODULE_form_views_exposed_form_alter(&$form, \Drupal\Core\Form\FormStateInterface $form_state, $form_id) {
$view = $form_state->getStorage('view');
$display_id = $view['view']->current_display;
if ($form_id == 'views_exposed_form' && $view['view']->id() == 'MY_VIEW' && $display_id == 'MY_VIEWDISPLAY') {
if (!empty($view['view']->args) && $view['view']->args[0]) {
//get the term ID from the contextual filter
$contextTermId = $view['view']->args[0];
$entriesToRemove = [];
$currentFilterValue = $form_state->getUserInput()['FIELD_FILTER_TAXONOMY'];
foreach ($form['FIELD_FILTER_TAXONOMY']['#options'] as $idx => $entry) {
if ($idx === 'All') {
//remove the old root '- Any -' option
$entriesToRemove[] = $idx;
}
//the next line is a bit shaky might need rework:
//sometimes filter entries are a stdClass,
//but I've also seen entries as array in other exposed forms (grouped filters?)
elseif ($entry instanceof stdClass && is_array($entry->option)) {
$termId = key($entry->option);
$termName = current($entry->option);
//the context filter term is our new root, so we change its label to '- Any -'
if ($termId == $contextTermId) {
$form['FIELD_FILTER_TAXONOMY']['#options'][$idx]->option = [$termId => t('- Any -')];
if (empty($currentFilterValue) || $currentFilterValue == 'All') {
//we've removed the default empty/All entry, reset it to our newly created, faked '- Any -' category
$form_state->setUserInput(['FIELD_FILTER_TAXONOMY' => $contextTermId]);
}
}
else {
//this is the core part: for each filter option load the term
//and check if it is a child of the contextual filter term
$parents = \Drupal::entityTypeManager()
->getStorage('taxonomy_term')
->loadParents($termId);
if (!in_array($contextTermId, array_keys($parents))) {
$entriesToRemove[] = $idx;
}
else {
//optional: we are in a sub-filter now,so we no longer need the leading '-' to indicate hierarchy
$form['FIELD_FILTER_TAXONOMY']['#options'][$idx]->option = [$termId => trim(preg_replace('/^-/', '', $termName))];
}
}
}
}
foreach ($entriesToRemove as $idx) {
unset($form['FIELD_FILTER_TAXONOMY']['#options'][$idx]);
}
//optional: if there is only 1 entry left, hide the filter
if (count($form['FIELD_FILTER_TAXONOMY']['#options']) == 1) {
$form['FIELD_FILTER_TAXONOMY'] = [
'#type' => 'hidden',
'value' => $contextTermId
];
}
}
}
}
注意の言葉:巨大な分類ではこれを行わないでください。私のコードはevery分類用語をロードして、削除する必要があるかどうかを判断します。
@Hudriが言ったように、MYMODULE_form_views_exposed_form_alter()
を使用してフォームを変更できます。
各用語をチェックして、その親がコンテキストフィルター引数であるかどうかを確認するのではなく、 TermStorage::loadTree()
メソッドを使用して、用語の下に用語のツリーをロードすることもできます。
$vocabulary_id = 'tags';
// Get this from your view object's contextual argument, e.g. $view->args[0], etc
$parent_id = 11;
$child_terms = \Drupal::entityTypeManager()
->getStorage('taxonomy_term')
->loadTree($vocabulary_id, $parent_id);
// Next build an options array of the child terms.
$child_term_options = [];
// Maybe you want an Any option
$child_term_options[''] = '- Any -';
foreach ($child_terms as $term) {
$child_term_options[$term->tid] = $term->name;
}
// Next update your filter options with only the child terms:
$form['MY_EXPOSED_FILTER']['#options'] = $child_term_options;