Upgrade Your Drupal Skills

We trained 1,000+ Drupal Developers over the last decade.

See Advanced Courses NAH, I know Enough

Some drupal pain about "q=user"

Parent Feed: 

In drupal, when you go to http://www.yoursite.com/?q=user you get redirected right away to http://www.yoursite.com/?q=user/777 (if 777 is your user id and if you are logged in). If you are not logged in, you see the login page.

My client wanted users to be redirected to http://www.yoursite.com/?q=user/me instead. How simple, right? WRONG!

Sometimes, (or often in Drupal) the simpliest thing end up being a nightmare.

I wrote a drupal module to handle this:

function foo_menu($may_cache) {
  if ($may_cache) {
    $items[] = array(
      'path' => 'user',
      'callback' => 'drupal_goto',
      'callback arguments' => array('user/me'),
    );
  }
  return $items;
}

I cleared my cache (thanks to the devel module) and I tried going to 'user'. Nope! I ended up on user/777 again.

I ended up figuring out why I was pulling my hear out doing this rather simple change. The problem was caused by the user.module which was doing something I did not expect.

As you know, the hook_menu($may_cache) is called twice. Once when you clear the cache and once for every request. When you clear the cache this hook is being called with TRUE as the $maycache parameters. You usually put menu items that can be cached (does not change dynamically). Most menu items can be cached. Some menu item like user/123/edit must load the node at run time before allowing you to see the content. But things like 'user' can be cached... so I thoughts.

The user module actually handle this two fold.

First:

  if ($may_cache) {
    $items[] = array('path' => 'user', 'title' => t('User account'),
      'callback' => 'drupal_get_form', 'callback arguments' => array('user_login'),
      'access' => !$user->uid, 'type' => MENU_CALLBACK);
  }
  else {
     // ...
  }

This is cached ($may_cached is TRUE) and is only accessible to logged out users and will present you the login form.

then you've got this which is causing my head to spin:

  if ($may_cache) {
     // ...
  else {
    if ($_GET['q'] == 'user' && $user->uid) {
      drupal_goto('user/'. $user->uid);
    }
  }

The "else" code is executed at every request, before the final decision is made. And this is calling drupal_goto right there right then which simply exit and stop all other menu hooks from ever being called. This is cheating!!! :)

The only way to fix that without hacking the core is to create a module with a ligther weight (change the weight column in the system table for that module) and implement a hook_menu that will run the same code as above but redirect elsewhere.

function foo_menu($may_cache) {
  if (!$may_cache) {
    if ($_GET['q'] == 'user' && $GLOBALS['user']->uid) {
      drupal_goto('user/me');
    }
  }
  return $items;
}

This will only work if your custom module is executed BEFORE the user module.
More details on "How to update a module's weight": http://drupal.org/node/110238

Author: 
RSS Tags: 
Original Post: 

About Drupal Sun

Drupal Sun is an Evolving Web project. It allows you to:

  • Do full-text search on all the articles in Drupal Planet (thanks to Apache Solr)
  • Facet based on tags, author, or feed
  • Flip through articles quickly (with j/k or arrow keys) to find what you're interested in
  • View the entire article text inline, or in the context of the site where it was created

See the blog post at Evolving Web

Evolving Web