In Drupal 7, from within a module,

My goal is having a menu path (e.g. "/path/to/page/%/%/view/%") and an array of arguments (e.g. array('foo1', 'foo2', 'foo3')), be able to build the resulting path (e.g. "/path/to/page/foo1/foo2/view/foo3").

After looking all over in the Drupal API, I cannot find a function that would do that.

Does such function exist?


The placeholders can be different as well. e.g. "/path/to/page/%user/%blah/view/%". The original raw path is dynamic and is only known during runtime.

I thought that format_string may work for %user and %blah, but what about the % in the end, does format_string work to replace that one too?


4 Answers 4


I don't think core has a function like that but it's easy enough to write a simple version:

$path = '/path/to/page/%foo/%bar/view/%';
$args = array('foo1', 'foo2', 'foo3');

$wildcards = array();
foreach (explode('/', $path) as $part) {
  if (strpos($part, '%') === 0) {
    $wildcards[] = $part;

if (count($args) != count($wildcards)) {
  // Handle it

foreach ($args as $key => $arg) {
  $wildcard = $wildcards[$key];
  $pos = strpos($path, $wildcard);
  if ($pos === FALSE) {

  $path = substr_replace($path, $arg, $pos, strlen($wildcard));
print $path;

Result is: /path/to/page/foo1/foo2/view/foo3

  • Yeah this should work, now the only case where this may not work is if the wildcard or placeholder can be a name, e.g. "%foo".
    – Weboide
    Commented Feb 25, 2014 at 15:02
  • Yeah that's a bit more complicated but not much, I've updated the answer
    – Clive
    Commented Feb 25, 2014 at 15:09
  • Oy. You can take the swing at _to_arg() substitutions next :)
    – Jimajamma
    Commented Feb 25, 2014 at 15:20
  • lol @Jimajamma, yeah this few line script is gonna get out of hand soon ;)
    – Clive
    Commented Feb 25, 2014 at 15:24
  • Looks like this is as close to a solution as it can get. The closest function I found that would do this is format_string() but it wouldn't really handle placeholders with '%' alone.
    – Weboide
    Commented Feb 25, 2014 at 18:05

You can use hook_menu function for creating url path from arguments, Drupal 7 doesn't support any direct function for creating menu :

Example :

function hook_menu() {
  $items['path/to/page/%/%/view/%'] = array(
    'title' => 'Example Page',
    'page callback' => 'example_page',
    'page arguments' => array(3,4,6),
    'access arguments' => array('access content'),

function example_page($foo1,$foo2,$foo3) {
 // Things  to  do.....

  • I already have my menu items set up. I'm looking into creating a custom URL from a raw path and using specific arguments to replace the placeholders within the raw path.
    – Weboide
    Commented Feb 25, 2014 at 14:55

If creating the path filled in with all the dynamic arguments is what you are after, not creating the Drupal menu callback to it, then certainly a quick php string manipulation can be done, eg, something along the lines of:

$path = 'path/to/page/%/%/view/%';
$args = array('foo1', 'foo2', 'foo3');
$wildcard = '%';

$path = str_replace($wildcard, '%s', $path);

$vpath=vsprintf($path, $args);

print $vpath; // path/to/page/foo1/foo2/view/foo3

Note: this quick and dull ax approach offers no error checking, and thus fails quite gracelessly when the number of arguments is less than what is expected.

  • Same as the other response, this should work, but now the only case where this may not work is if the wildcard or placeholder is a name, e.g. "%foo". I've edited the OP.
    – Weboide
    Commented Feb 25, 2014 at 15:03
  • as those are mostly loaders and thus take numeric arguments, with some edge cases like mappings and such, what are you trying to do exactly with this result? and how are you getting the input?
    – Jimajamma
    Commented Feb 25, 2014 at 15:14
  • I have a filter form for a report, and after picking a few values and submitting the form, you are redirected to the clean URL forthe report using the submitted filters (that way you can share the clean URL with anyone). The thing is that the original raw path is dynamic and not known.
    – Weboide
    Commented Feb 25, 2014 at 17:57
  • If you are sitting somewhere within Drupal, and got there via a hook_menu(), $_GET['q'] will have the original system path you are sitting on, and (most probably) $_SERVER['REQUEST_URI'] will contain similar, or the alias. Or am I missing something still?
    – Jimajamma
    Commented Feb 25, 2014 at 19:04
  • But I already have the original path, I'm building a new one based on the original "raw" path, but using different parameters. It's a basic replace function, but with named parameters and stuff makes it not so basic so I thought there would be a system function for that, somewhat similar to format_string().
    – Weboide
    Commented Feb 25, 2014 at 23:04

I ended up building a simple version based on _menu_router_build.

function build_path($raw_path, $parameters)
  $new_path = '';
  $parts = explode('/', $raw_path);

  foreach($parts as $part)
    // Look for wildcards in the form allowed to be used in PHP functions,
    // and if we do find one, then replace it with the next variable
    if(preg_match('/^%(|' . DRUPAL_PHP_FUNCTION_PATTERN . ')$/', $part))
      $part = array_shift($parameters);

      $new_path .= '/';
    $new_path .= $part;

  // add remaining parameters at the end
  foreach($parameters as $parameter)
    $new_path .= '/'.$parameter;

  return $new_path;

echo build_path('category/%cat/view/%', array('cat1','id123','extravar1','extravar2'));

Prints category/cat1/view/id123/extravar1/extravar2

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.