Last updated February 2, 2009. Created by Gerhard Killesreiter on February 2, 2009.
Log in to edit this page.

Imagine you are using Drupal's multisite feature to set up a couple of websites for a client. After a while the client decides that multisite is nice and dandy, but that the menu should be slightly different for each of them.

In my case the menu was for a product catalog and some of the branches didn't carry the full array of stocks. If this happens, the menu entry for that kind of stock should not be shown.

To achieve this, I've first implemented hook_menu_alter:

function mymodule_menu_alter(&$callbacks) {
  foreach ($callbacks as $path => &$callback) {
    if ((some condition on the callback or the path)) {
      // we set a special callback our callback
      $callback['access callback'] = 'mymodule_menu_access';
      // we pass along some arguments that we may need later, here we use the path.
      $callback['access arguments'] = array($path);
    }
  }
}

Then we implement the access function:

function mymodule_menu_access($path) {
  static $access = array();
  if ($path) {
    if (!count($access)) {
      $result = db_query((Some query to get access conditions for the possible paths. This query would depend on the subsite chosen));
      while ($condition = db_fetch_object($result)) {
        $access[$condition->path] = TRUE;
      }
    }
    if (isset($access[$path])) {
      return TRUE;
    }
    else {
      return FALSE;
    }
  }
  else {
    return TRUE;
  }
}

Note that we've cached the output of the query statically in an array. This way we only need to do one query per page load. If the query is heavy it would be an option to cache the result in the database or memcached.

Looking for support? Visit the Drupal.org forums, or join #drupal-support in IRC.