0

Are we allowed to use the same path for two different routes? For example, can I use the following code?

function mymodule_menu() {
  $items['myUrl/dboperation'] = array(
    'title' => 'some custom db operation for insert',
    'page callback' => 'mydboperation1',
    'access callback' => TRUE,
    'file' => 'my_dboperation.inc',
  );

  $items['myUrl/dboperation'] = array(
    'title' => 'some custom db operation for delete',
    'page callback' => 'mydboperation2',
    'access callback' => TRUE,
    'file' => 'my_dboperation.inc',
  );

  return $items;
}

The code doesn't work. It works when I change the second path.

I was searching for the answer and came across How should I implement hook_menu()? but it doesn't explain what to use for the route path.

Why doesn't my code work? What should I instead use to make it work?

7
  • Let me ask you a question back, what would you expect to see when you do the above? Really, the answer to this question is a very fundamental PHP question, so I think this is actually off-topic for the site.
    – Letharion
    Sep 14, 2014 at 14:15
  • I wanted to have a common url for two operation, in php also we usually differentiate it by using query string like /myFile.php?op=insert so I just wanted to check how the drupal hook works.
    – Hitesh
    Sep 15, 2014 at 4:43
  • @Letharion : Why I asked this question ?...first not even one function out of both hooks were working and both had an empty response in network console. secondly, I didn't see any error in console, so to clarify my doubts and have better understanding of how hook works. I asked this question ... If you still think it is off topic , please explain sothat I can improve myself !!!! Thanks!!!!!
    – Hitesh
    Sep 15, 2014 at 4:53
  • 1
    If you are familiar with PHP, please consider the following. What would be the value of $items as returned by your code above? Your question as it stands, doesn't actually make sense, unless it's a fundamental PHP question. And if it is, it's off topic on this site.
    – Letharion
    Sep 15, 2014 at 6:04
  • 1
    The point I'm failing to get across, is that the answer is staring right back at you, and I'm trying to get you to figure it out. If you read your own code carefully, you'll see that what you are proposing couldn't possibly work, whether Drupal supports it or not.
    – Letharion
    Sep 15, 2014 at 8:43

4 Answers 4

1

The short answer is NO.
Your would ether make a different path to each function or send an argument to a single function through the url.
eg. different path:

function mymodule_menu() {

    $items['myUrl/dboperation/insert'] = array(
        'title' => 'some custom db operation for insert',
        'page callback' => 'mydboperation1',
        'access callback' => TRUE,
        'file' => 'my_dboperation.inc',
    );

    $items['myUrl/dboperation/delete'] = array(
        'title' => 'some custom db operation for delete',
        'page callback' => 'mydboperation2',
        'access callback' => TRUE,
        'file' => 'my_dboperation.inc',
    );

    return $items;
}

See the hook_menu docs for how to send an argument if you choose to do it that way.

0

The answer for this question is very simple

When we create 2 menus with same path and different function then the menu taken later will override the first one if they have the same weight.

It is same like when we create an array with same key and assign different values to it then the array taken at the second position override the value of first one if they have the same weight

<?php
$ar = array();
$ar['name'] = 'Raj'; //same like first menu
$ar['name'] = 'Thakur';  //second menu


print $ar['name']; //It will print **Thakur**
?>

Same concept is used for menus if they have the same weight, however you can give more priority to any menu using 'weight' parameter.

You can override any menu by its weight

<?php
 $items['myUrl/dboperation'] = array(
        'title' => 'some custom db operation for insert',
        'page callback' => 'mydboperation1',
        'access callback' => TRUE,
        'file' => 'my_dboperation.inc',
        'weight'=>2 

    );

    $items['myUrl/dboperation'] = array(
        'title' => 'some custom db operation for delete',
        'page callback' => 'mydboperation2',
        'access callback' => TRUE,
        'file' => 'my_dboperation.inc',
         'weight'=1 

    );
?>

This menu second menu can take the higher priority over the first one.

And any change in menu need to clear cache.

Hope it will answer your question.

6
  • I think you are wrong about the weight, the priority should depend on module's weight. From hook_menu documentation: "weight": An integer that determines the relative position of items in the menu; higher-weighted items sink. Defaults to 0. Menu items with the same weight are ordered alphabetically.
    – Saulius
    Sep 13, 2014 at 18:15
  • It can be, just try by adding the weight parameter. So we people get to know. I haven't test the code for weight param in my machine.
    – user33576
    Sep 13, 2014 at 18:20
  • if what you say is true than why does it not work for second url, I was having a blank response for both the hook menu
    – Hitesh
    Sep 15, 2014 at 4:46
  • It worked for second url, it overrides the fist menu
    – user33576
    Sep 15, 2014 at 5:36
  • 1
    It's an array of menu items. Whenever you assign 2 array elements with the same key the one that comes later in the code will override previous ones. The menu item weight has nothing to do with it, that is for the order of the menu item within the menu.
    – rooby
    Sep 16, 2014 at 5:32
0

Weight is used to arrange menu items in menu. You can use hook_menu_alter to alter your menu items functionality.

https://api.drupal.org/api/drupal/modules%21system%21system.api.php/function/hook_menu_alter/7

1
  • Adding the weight to the code shown from the OP would not make two routes. It's plain PHP: The code is setting the same array index twice.
    – apaderno
    May 16, 2016 at 5:48
0

The reason why the code doesn't work is that the same array index is being set twice. In that case, only the last value set is kept. That code is exactly equivalent to the following one.

function mymodule_menu() {
  $items['myUrl/dboperation'] = array(
    'title' => 'some custom db operation for delete',
    'page callback' => 'mydboperation2',
    'access callback' => TRUE,
    'file' => 'my_dboperation.inc',
  );

  return $items;
}

If you want to make it work, you have two possibilities: Define two different paths, or use wildcard arguments.

In the first case, you need to make the code similar to the following one.

function mymodule_menu() {
  $items['myUrl/dboperation/insert'] = array(
    'title' => 'Insert data in the database',
    'page callback' => 'mymodule_database_insert',
    'access callback' => TRUE,
    'file' => 'my_dboperation.inc',
  );

  $items['myUrl/dboperation/delete'] = array(
    'title' => 'Delete data from the database',
    'page callback' => 'mymodule_database_delete',
    'access callback' => TRUE,
    'file' => 'my_dboperation.inc',
  );

  return $items;
}

I changed the callback names because in Drupal it is preferable that functions implemented by a module are prefixed with the machine name of the module, to avoid conflicts with other modules.

The second alternative is using wildcard arguments, which allows to pass arguments to the page callback, making it more helpful. It also make extending the code easier, and less error-prone, since there isn't the need to add a new route for new operations. In the following code, I am using the first argument to decide the operation that must be done on the database, while the second argument is a generic one, and it could be used to decide on which data the operation must be performed.

function mymodule_menu() {
  $items['myUrl/dboperation/%/%'] = array(
    'title' => 'Change data in the database',
    'page callback' => 'mymodule_database_operation',
    'page arguments' => array(2,3),
    'access callback' => TRUE,
    'file' => 'my_dboperation.inc',
  );
  return $items;
}

function mymodule_database_operation($op, $arg) {
  switch $op {
    case 'insert':
      // Insert data.
      break;
    case 'delete':
      // Delete data.
      break;
  }
}

Your Answer

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

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