İki modül 'hook_menu'da aynı menü yolunu tanımladıysa, hangisi Drupal'ı seçer?


14

Örneğin, "moduleone" çıktı veren 'admin / hello' yolunu tanımlar print_moduleone_stuff().

/**
 * Implements hook_menu()
 */
function moduleone_menu() {
  $items['admin/hello'] = array(
    'title' => 'Module One Hello World',
    'page callback' => print_moduleone_stuff,
  );
  return $items;
}

"moduletwo" çıktı veren 'admin / hello' yolunu tanımlar print_moduletwo_stuff().

/**
 * Implements hook_menu()
 */
function moduletwo_menu() {
  $items['admin/hello'] = array(
    'title' => 'Module Two Hello World',
    'page callback' => print_moduletwo_stuff,
  );
  return $items;
}

Her iki modül de farklı sonuç için 'admin / hello' yolunu tanımladı. Bu iki modül etkinleştirildiğinde, Drupal birini diğerinden nasıl seçer? Drupal çatışmayı nasıl çözer?

Yanıtlar:


16

Çağıran işlev hook_menu(), menu_rebuild () tarafından çağrılan menu_router_build () işlevidir . Aşağıdaki kodu içerir.

  foreach (module_implements('menu') as $module) {
    $router_items = call_user_func($module . '_menu');
    if (isset($router_items) && is_array($router_items)) {
      foreach (array_keys($router_items) as $path) {
        $router_items[$path]['module'] = $module;
      }
      $callbacks = array_merge($callbacks, $router_items);
    }
  }
  // Alter the menu as defined in modules, keys are like user/%user.
  drupal_alter('menu', $callbacks);

Aynı yolu tanımlayan iki modül varsa, tarafından döndürülen dizideki son modül module_implements()diğer modüllerden tanımlanan değeri geçersiz kılar.

Gerekli olan ikinci parametre module_implements()şu şekilde tanımlanır:

$sortVarsayılan olarak, modüller ağırlık ve dosya adına göre sıralanır, bu seçeneğin ayarlandığı gibi TRUE, modül listesi modül adına göre sıralanır.

Yana menu_router_build()için ikinci parametre geçmez menu_implements(), işlevi bu parametre için varsayılan bir değer kullanıyor. Bu, modül listesinin ağırlıklarına ve dosya adlarına göre sıralandığı anlamına gelir; iki modül aynı ağırlığa sahip olduğunda, listede görünen ilk modül alfabetik olarak önce gelen modüldür.

Ayrıca, herhangi bir modül uygulaması hook_module_implements_alter(), kancaların çağrılma sırasını değiştirebilir.

Bu nedenle, kancaların hangi sırayla çağrıldığını bilmemelisiniz.
Kodun amacı başka bir modül tarafından uygulanan rotayı değiştiriyorsa, örneğin ikinci bir modül kurulduğunda ve etkinleştirildiğinde bir yolun kaldırılması gerektiğinden, kod kullanılmalıdır hook_menu_alter(). Rota çakışmaları durumunda hangi modülün "kazanacağını" anlamaya çalışıyorsanız, böyle bir rota çakışmasından kaçınmayı ve başka bir modülden tanımlanmamış bir rotayı tanımlamayı tercih ederim.

O zaman uyguluyorsanız hook_menu_alter()ve modülünüzün en son yürütüldüğünden emin olmak istiyorsanız, bir rotayı etkili bir şekilde geçersiz kılan modül olmak için de uygulamanız gerekir hook_module_implements_alter().

function mymodule_module_implements_alter(&$implementations, $hook) {
  if ($hook == 'menu_alter') {
    // Move mymodule_menu_alter() to the end of the list. module_implements()
    // iterates through $implementations with a foreach loop which PHP iterates
    // in the order that the items were added, so to move an item to the end of
    // the array, we remove it and then add it.
    $group = $implementations['mymodule'];
    unset($implementations['mymodule']);
    $implementations['mymodule'] = $group;
  }
}

çok açık ve yardımsever, teşekkürler. ayrıca bu durumda hook_menu_alter () kullanımını belirttiğiniz için teşekkür ederiz.
Ocak'ta gilzero

iki modül hook_menu_alter () içinde aynı yolu tanımlarsa ne olur? aynı kurallar uygulanıyor mu?
gilzero

hook_menu_alter()yeni menüleri tanımlamak için değil, mevcut menüleri değiştirmek için kullanılır. İki modül aynı menüyü değiştirirse, kalan değişiklik modülden yapılan modüldür.
kiamlaluno

4

Hangi modül daha düşük sahip weightdeğer systemdaha yüksek modül böylece bir tabloda ilk çağrılacak weightdeğeri bu durumda 'kazanmak' olacak.

Ağırlıklar iki (veya daha fazla) modül için aynı ise, doğrudan MySQL tablosundan gelen sipariş dışında yapılan özel bir sipariş olmadığına inanıyorum (bu konuda yanlış olabilirim).

Çağrılmasından elde edilen dönüş sonuçları hook_menusadece tek bir menü öğesi dizisine konduğundan, hiçbir zaman bir 'çakışma' olmayacak, daha sonra yapılan çağrıların sonuçlarıhook_menu olmayacak önceki çağrıların geçersiz kılacaktır.


4
Göre Pro Drupal Geliştirme , eşit ağırlığa sahip modüller kendi sistem adına göre alfabetik olarak adlandırılır.
mpdonadio

2
Bu kitap tarafından bildirilenler doğrudur: Bir kanca uygulayan modüllerin listesi genellikle ağırlık ve alfabetik olarak sıralanır; ikinci parametre olarak module_implements()alırsa sıralanmaz FALSE, ancak module_invoke_all()yalnızca bir parametre ile çağırır gibi işlev görür .
kiamlaluno

Önceki yorumum tam olarak doğru değil. Cevabımda bildirdiklerim doğru.
kiamlaluno
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.