В данной статье мы рассмотрим, как связать зависимые списки из разных типов материалов в Drupal. Эта задача может возникнуть, например, когда вы хотите, чтобы выбор одного элемента в первом списке динамически обновлял второй список с учетом зависимостей.

Шаг 1: Создание типов материалов

Первым шагом является создание двух типов материалов, которые будут использоваться для отображения списков. Давайте назовем эти типы «Страны» и «Города».

function mymodule_install() {
  // Создаем тип материала "Страны"
  $country_type = \Drupal::entityTypeManager()->getDefinition('node_type')->getBundleEntityType();
  $country_bundle = 'country';
  NodeType::create([
    'type' => 'country',
    'name' => 'Страны',
    'base' => $country_type,
  ])->save();
  
  // Создаем тип материала "Города"
  $city_type = \Drupal::entityTypeManager()->getDefinition('node_type')->getBundleEntityType();
  $city_bundle = 'city';
  NodeType::create([
    'type' => 'city',
    'name' => 'Города',
    'base' => $city_type,
  ])->save();
}

Шаг 2: Создание полей зависимых списков

Далее нам необходимо создать поля для связи между типами материалов. Для этого мы будем использовать модуль «Entity reference». Создадим поле «Страна», которое будет ссылаться на тип материала «Страны».

// Создаем поле "Страна" для типа материала "Города"
$field_storage = FieldStorageConfig::create([
  'field_name' => 'field_country',
  'entity_type' => 'node',
  'type' => 'entity_reference',
  'settings' => array(
    'target_type' => 'node',
    'target_bundles' => array('country'),
  ),
]);
$field_storage->save();

$field_instance = FieldConfig::create([
  'field_storage' => $field_storage,
  'bundle' => 'city',
  'label' => 'Страна',
  'required' => TRUE,
]);
$field_instance->save();

Шаг 3: Создание зависимых списков

Последний шаг — настройка автоматического обновления второго списка на основе выбора из первого списка. Для этого используется модуль «Conditional Fields». Создадим пример кода для зависимых списков в форме добавления материала «Города».

// Зависимый список "Города"
$form['field_country']['widget'][0]['target_id']['#ajax'] = array(
  'event' => 'change',
  'callback' => 'mymodule_update_cities_list_callback',
  'wrapper' => 'cities-wrapper',
);

// Обновление списка городов при выборе страны
function mymodule_update_cities_list_callback($form, $form_state) {
  $country_id = $form_state->getValue('field_country')[0]['target_id'];
  
  $query = \Drupal::entityQuery('node')
    ->condition('type', 'city')
    ->condition('field_country', $country_id);
  $city_ids = $query->execute();
  
  $city_options = array();
  foreach ($city_ids as $city_id) {
    $city = Node::load($city_id);
    $city_options[$city_id] = $city->getTitle();
  }
  
  $form['field_city']['widget'][0]['target_id']['#options'] = $city_options;
  
  return $form['field_city'];
}

Вопросы и ответы

1. Как настроить автоматическое обновление списка на основе выбора из другого списка?

Чтобы настроить автоматическое обновление списка на основе выбора из другого списка, вы можете использовать модуль «Conditional Fields». Вам нужно добавить AJAX-обработчик, который будет вызываться при изменении значения в первом списке и обновлять содержимое второго списка в зависимости от выбранного значения.

2. Как создать поля зависимых списков в Drupal?

Чтобы создать поля зависимых списков в Drupal, вам понадобится модуль «Entity reference». Он позволит создать поле, которое будет ссылаться на другой тип материала. Выберите нужный тип материала в настройках поля и настройте его отображение на форме добавления или редактирования материала.

3. Можно ли связать списки из разных типов материалов без использования модулей?

Да, это возможно. Вы можете создать свои собственные модули и написать код, который будет связывать списки из разных типов материалов. Однако использование модулей, таких как «Entity reference» и «Conditional Fields», значительно упрощает и ускоряет процесс разработки.