4.7.x path.inc drupal_lookup_path($action, $path = '')
5.x path.inc drupal_lookup_path($action, $path = '')
6.x path.inc drupal_lookup_path($action, $path = '', $path_language = '')
7.x path.inc drupal_lookup_path($action, $path = '', $path_language = NULL)

Given an alias, return its Drupal system URL if one exists. Given a Drupal system URL return one of its aliases if such a one exists. Otherwise, return FALSE.

Parameters

$action: One of the following values:

  • wipe: delete the alias cache.
  • alias: return an alias for a given Drupal system path (if one exists).
  • source: return the Drupal system URL for a path alias (if one exists).

$path: The path to investigate for corresponding aliases or system URLs.

$path_language: Optional language code to search the path with. Defaults to the page language. If there's no path defined for that language it will search paths without language.

Return value

Either a Drupal system path, an aliased path, or FALSE if no path was found.

5 calls to drupal_lookup_path()
drupal_get_normal_path in includes/path.inc
Given a path alias, return the internal path it represents.
drupal_get_path_alias in includes/path.inc
Given an internal Drupal path, return the alias set by the administrator.
LocalePathFunctionalTest::testPathLanguageConfiguration in modules/locale/locale.test
Test if a language can be associated with a path alias.
PathLanguageTestCase::testAliasTranslation in modules/path/path.test
Test alias functionality through the admin interfaces.
PathLookupTest::testDrupalLookupPath in modules/simpletest/tests/path.test
Test that drupal_lookup_path() returns the correct path.
3 string references to 'drupal_lookup_path'
drupal_cache_system_paths in includes/path.inc
Cache system paths for a page.
drupal_clear_path_cache in includes/path.inc
Clear the path cache.
PathTestCase::testAdminAlias in modules/path/path.test
Tests alias functionality through the admin interfaces.

File

includes/path.inc, line 45
Functions to handle paths in Drupal, including path aliasing.

Code

function drupal_lookup_path($action, $path = '', $path_language = NULL) {
  global $language_url;
  // Use the advanced drupal_static() pattern, since this is called very often.
  static $drupal_static_fast;
  if (!isset($drupal_static_fast)) {
    $drupal_static_fast['cache'] = &drupal_static(__FUNCTION__);
  }
  $cache = &$drupal_static_fast['cache'];

  if (!isset($cache)) {
    $cache = array(
      'map' => array(),
      'no_source' => array(),
      'whitelist' => NULL,
      'system_paths' => array(),
      'no_aliases' => array(),
      'first_call' => TRUE,
    );
  }

  // Retrieve the path alias whitelist.
  if (!isset($cache['whitelist'])) {
    $cache['whitelist'] = variable_get('path_alias_whitelist', NULL);
    if (!isset($cache['whitelist'])) {
      $cache['whitelist'] = drupal_path_alias_whitelist_rebuild();
    }
  }

  // If no language is explicitly specified we default to the current URL
  // language. If we used a language different from the one conveyed by the
  // requested URL, we might end up being unable to check if there is a path
  // alias matching the URL path.
  $path_language = $path_language ? $path_language : $language_url->language;

  if ($action == 'wipe') {
    $cache = array();
    $cache['whitelist'] = drupal_path_alias_whitelist_rebuild();
  }
  elseif ($cache['whitelist'] && $path != '') {
    if ($action == 'alias') {
      // During the first call to drupal_lookup_path() per language, load the
      // expected system paths for the page from cache.
      if (!empty($cache['first_call'])) {
        $cache['first_call'] = FALSE;

        $cache['map'][$path_language] = array();
        // Load system paths from cache.
        $cid = current_path();
        if ($cached = cache_get($cid, 'cache_path')) {
          $cache['system_paths'] = $cached->data;
          // Now fetch the aliases corresponding to these system paths.
          $args = array(
            ':system' => $cache['system_paths'],
            ':language' => $path_language,
            ':language_none' => LANGUAGE_NONE,
          );
          // Always get the language-specific alias before the language-neutral
          // one. For example 'de' is less than 'und' so the order needs to be
          // ASC, while 'xx-lolspeak' is more than 'und' so the order needs to
          // be DESC. We also order by pid ASC so that fetchAllKeyed() returns
          // the most recently created alias for each source. Subsequent queries
          // using fetchField() must use pid DESC to have the same effect.
          // For performance reasons, the query builder is not used here.
          if ($path_language == LANGUAGE_NONE) {
            // Prevent PDO from complaining about a token the query doesn't use.
            unset($args[':language']);
            $result = db_query('SELECT source, alias FROM {url_alias} WHERE source IN (:system) AND language = :language_none ORDER BY pid ASC', $args);
          }
          elseif ($path_language < LANGUAGE_NONE) {
            $result = db_query('SELECT source, alias FROM {url_alias} WHERE source IN (:system) AND language IN (:language, :language_none) ORDER BY language ASC, pid ASC', $args);
          }
          else {
            $result = db_query('SELECT source, alias FROM {url_alias} WHERE source IN (:system) AND language IN (:language, :language_none) ORDER BY language DESC, pid ASC', $args);
          }
          $cache['map'][$path_language] = $result->fetchAllKeyed();
          // Keep a record of paths with no alias to avoid querying twice.
          $cache['no_aliases'][$path_language] = array_flip(array_diff_key($cache['system_paths'], array_keys($cache['map'][$path_language])));
        }
      }
      // If the alias has already been loaded, return it.
      if (isset($cache['map'][$path_language][$path])) {
        return $cache['map'][$path_language][$path];
      }
      // Check the path whitelist, if the top_level part before the first /
      // is not in the list, then there is no need to do anything further,
      // it is not in the database.
      elseif (!isset($cache['whitelist'][strtok($path, '/')])) {
        return FALSE;
      }
      // For system paths which were not cached, query aliases individually.
      elseif (!isset($cache['no_aliases'][$path_language][$path])) {
        $args = array(
          ':source' => $path,
          ':language' => $path_language,
          ':language_none' => LANGUAGE_NONE,
        );
        // See the queries above.
        if ($path_language == LANGUAGE_NONE) {
          unset($args[':language']);
          $alias = db_query("SELECT alias FROM {url_alias} WHERE source = :source AND language = :language_none ORDER BY pid DESC", $args)->fetchField();
        }
        elseif ($path_language > LANGUAGE_NONE) {
          $alias = db_query("SELECT alias FROM {url_alias} WHERE source = :source AND language IN (:language, :language_none) ORDER BY language DESC, pid DESC", $args)->fetchField();
        }
        else {
          $alias = db_query("SELECT alias FROM {url_alias} WHERE source = :source AND language IN (:language, :language_none) ORDER BY language ASC, pid DESC", $args)->fetchField();
        }
        $cache['map'][$path_language][$path] = $alias;
        return $alias;
      }
    }
    // Check $no_source for this $path in case we've already determined that there
    // isn't a path that has this alias
    elseif ($action == 'source' && !isset($cache['no_source'][$path_language][$path])) {
      // Look for the value $path within the cached $map
      $source = FALSE;
      if (!isset($cache['map'][$path_language]) || !($source = array_search($path, $cache['map'][$path_language]))) {
        $args = array(
          ':alias' => $path,
          ':language' => $path_language,
          ':language_none' => LANGUAGE_NONE,
        );
        // See the queries above.
        if ($path_language == LANGUAGE_NONE) {
          unset($args[':language']);
          $result = db_query("SELECT source FROM {url_alias} WHERE alias = :alias AND language = :language_none ORDER BY pid DESC", $args);
        }
        elseif ($path_language > LANGUAGE_NONE) {
          $result = db_query("SELECT source FROM {url_alias} WHERE alias = :alias AND language IN (:language, :language_none) ORDER BY language DESC, pid DESC", $args);
        }
        else {
          $result = db_query("SELECT source FROM {url_alias} WHERE alias = :alias AND language IN (:language, :language_none) ORDER BY language ASC, pid DESC", $args);
        }
        if ($source = $result->fetchField()) {
          $cache['map'][$path_language][$source] = $path;
        }
        else {
          // We can't record anything into $map because we do not have a valid
          // index and there is no need because we have not learned anything
          // about any Drupal path. Thus cache to $no_source.
          $cache['no_source'][$path_language][$path] = TRUE;
        }
      }
      return $source;
    }
  }

  return FALSE;
}

Comments

swirt’s picture

I was doing a bit of research into which was faster, url() or drupal_lookup_path() or drupal_get_path_alias().
I found no declared speed winner, but I did notice that only the url() function is documented out to D8.

jcfiala’s picture

Well, url() calls drupal_get_path_alias() which calls drupal_lookup_path(), at least for Drupal 7. So I would expect the speed to reflect that.

angel.h’s picture

I just realized that this function not only returns a path by path given but it can also delete path alias????? What's up with this? That's just plainly wrong.

akoepke’s picture

I think you misread the code or docs. It deletes the alias CACHE if you ask it to, but doesn't delete a path alias.

rudiedirkx’s picture

This function doesn't respect language. The cache id ($cid) is language agnostic, so the first language it caches, is in luck. If 1 node has several aliases (1 per language), it fails. Adding the language code to the cache id fixes that:

$cid .= ':' . $path_language;
rudiedirkx’s picture

Or actually it just bypasses the cache always, not the best thing.

cubeinspire’s picture

I've found a bug on this function on Drupal7 (or maybe it's on pathauto)
How to reproduce:

1. Created an extra field "full_name".
2. I installed pathauto and created a pattern for all user's profiles with the token of the "full name" field.
3. On template I try to get the link to the profile using
$user_link = drupal_get_path_alias('user/' . $node->uid);

The link saved on $user_link leads to a 404 and it's like:
/user/username
intead of:
/u/sergio-garcia-fernandez

Any suggestion about where to implment the patch? core or pathauto?