I'm having trouble understanding hook_menu() where it says:

"page arguments": An array of arguments to pass to the page callback function. Integer values pass the corresponding URL component (see arg()).

I'd like to pass an argument through the page URL to the function mymodule_startpage() in the example below:

function mymodule_menu() {

  $items = array();

  $items['mymodule-startpage'] = array(
    'page callback' => 'drupal_get_form',
    'page arguments' => array('mymodule_startpage', 1),   //doesn't work as expected
    'access arguments' => array('mymodule access'),
    'type' => MENU_SUGGESTED_ITEM,
  );

  return $items;

}

function mymodule_startpage($myarg) {

...

}

I don't get the URL component in $myarg. However, if I add this to my function:

$myarg = arg(1);

it gives me the part of the URL that I want. What am I doing wrong? Thanks in advance!

Comments

styro’s picture

This is just guesswork....

Your page arguments have an argument 1

'page arguments' => array('mymodule_startpage', 1)

but your menu path only has argument 0

$items['mymodule-startpage'] = array(

What happens of you add a wildcard argument 1 to your path:

$items['mymodule-startpage/%'] = array(

hcbowman’s picture

Thanks for looking at this, but your suggestion

$items['mymodule-startpage/%'] = array(

acts just like my original code.

It seems like drupal_get_form() is eating the extra argument in 'page arguments', and I can't figure out why by reading the source.

Thanks!

qpal’s picture

Hi,
It may work this way:

$items['mymodule-startpage/%'] -- this indicates that your path is mymodule-startpage and you want to pass the argument %

'page callback' => 'mymodule_startpage', -- this property is the one that call your call back function, mymodule_startpage()

'page arguments' => array(1), -- this property is the one that pass the actual argument to the function, since your path has two argument, mymodule-startpage is argument 1 (array(0) ) and % is the dynamic argument and it is array(1)

Hope it helps.

josepvalls’s picture

Did you manage to get that working?
I'm trying to accomplish something similar.
I have a meenu with a function callback.
From the callback, I get the parameters properly and I can print them.

Then I have a form. I can do a drupal_get_form in my callback function and I get the form.
So far so good, but I want to set some form values based on the parameter, how do I get those to the form function?

jaypan’s picture

function mymodule_form()
{
  $menu['path/%'] = array
  (
    'page callback' => 'drupal_get_form',
    'page arguments' => array('mymodule_myform', 1), // 1 is the wildcard in the URL
    // put rest of menu item declaration here
  );
  return $menu;
}

function mymodule_myform($form_state, $variable) // $form_state is passed to all form callbacks. $variable is the wildcard from the URL
{
  $form['variable'] = array
  (
    '#value' => $variable,
  );
  return $form;
}

This will print the value from the wildcard in the URL to the screen.

Contact me to contract me for D7 -> D10/11 migrations.

josepvalls’s picture

Jay, thanks for the quick reply.
In my callback function I actually need to do some operations on the arguments and then I call the drupal_get_form. And from the documentation, drupal_get_form
only takes one argument and then hook_form(&$node, $form_state) seems to get only 2 parameters, and no extra arguments. Is this right? Can I use form_state to pass in my extra information? If so, how do I call it?

//this is my menu callback function where I get the arguments an process them
$content .= "</p>"
$content .= drupal_get_form('valls_forms_my_form'); 

and then I have a separate form function

function valls_forms_my_form($form_state) {
  $form = array();
//here is where I need to set the form value.
//right now I'm using arg() to get it
//but I have duplicate processing of the arguments

Thanks!

jaypan’s picture

drupal_get_form() only takes one argument by default, but you can add more if you want.

function mymodule_form()
{
  $menu['path/%'] = array
  (
    'page callback' => 'my_module_myfunction',
    'page arguments' => array(1), // 1 is the wildcard in the URL
    // put rest of menu item declaration here
  );
  return $menu;
}

function my_module_myfunction($url_argument) // $url is the value from the url, passed in the 'page arguments' of the menu declaration
{
  $variable = 'The value in the URL was ' . $url_argument;
  return drupal_get_form('mymodule_my_form, $variable); // notice we pass variable to drupal_get_form()
}

function mymodule_myform($form_state, $variable) // $variable has been passed from my_module_my_function
{
  $form['variable'] = array
  (
    '#value' => $variable,
  );
  return $form;
}

Contact me to contract me for D7 -> D10/11 migrations.

josepvalls’s picture

I'll give it a try right away.
Thanks!

Anonymous’s picture

You can just add the argument to the url and the use arg() to process it.

jaypan’s picture

You can, but it's not a good way to do it as it can cause problems if the form is embedded in other pages. arg() will change depending on the depth of the URL that the form is embedded in.

Contact me to contract me for D7 -> D10/11 migrations.

scottsawyer’s picture

I'm guessing the original thread was for Drupal 6.

For Drupal 7

hook_menu() {
  $items['my_form/%'] = array(
    'page callback' => 'drupal_get_form',
    'page arguments' => array('my_form_function', 1),  // '1' being the 2nd position in the path. 0/1
  );
  return $items;
}
function my_form_function ($form, &$form_state, $variable) {
  //... awesome form stuff
}

Hope it saves someone 10 minutes :)

ScottSawyerConsulting.com

jaypan’s picture

I'm guessing the original thread was for Drupal 6.

It was (and the thread is marked D6). Your solution for D7 was correct. To clarify:

Form definition with argument - D6:

function some_form($form_state, $argument)

Form definition with argument - D7:

function some_form($form, &$form_state, $argument)

Contact me to contract me for D7 -> D10/11 migrations.

abbas.mulani’s picture

Thanks for adding D7 syntax

function some_form($form, &$form_state, $argument) {}

It worked for me.

Abbas.

bribread22’s picture

The key to passing variables to functions from hook_menu to a function is the index position of the wildcard for a particular items element. Getting the page arguments key correct is critical to this working.

<?php
/**
 * Implements hook_menu().
 */
function example_menu() {
  // In this example, the third parameter will be passed.
  $items['admin/example/%'] = array(
    'title' => 'Example of first parameter being passed',
    'description' => 'This has a page arguments index of two because the wildcard occurs at the 3rd parameter',
    'page callback' => 'one',
    'page arguments' => array(2),
    'access arguments' => array('access administration pages'),
  );
  // The third and fourth parameters are being passed, hence we need to create an array with values 2 and 3 for the page arguments key
  $items['admin/example/%/%'] = array(
    'title' => 'Example of multiple parameters being submitted',
    'description' => 'Example of multiple parameters being submitted',
    'page callback' => 'two',
    'page arguments' => array(2, 3),
    'access arguments' => array('access administration pages'),
  );

  return $items;
}

/**
 * One parameter being passed.
 */
function one($one) {
    return $one;
}

/**
 * Two parameters being passed.
 */
function two($one, $two) {
    return $one . ' ' . $two;
}
?>
jasonhoward7’s picture

Shouldn't your function for "Two parameters being passed." be:
function two($one,$two) {...

bribread22’s picture

Yes, you're right. It looks like I forgot to rename that second function to two. I guess it would make more sense if I was demonstrating overloading.

ssanchez77’s picture

Thank you!! This helped me a lot!!

Just one observation: I was making some modifications in the arguments array, but the results were not the expected.

The problem was that I had to disable and enable the module again, because (according to the hook_menu documentation) "this hook is rarely called (for example, when modules are enabled), and its results are cached in the database".

jaypan’s picture

You can clear the menu cache, rather than disabling and re-enabling your module.

Contact me to contract me for D7 -> D10/11 migrations.

hem_awalker’s picture

Just a quick FYI.
 

    $items = array(
        'test/setup/%' => array(
            'title' => 'Test Form',
            'page callback' => 'drupal_get_form',
            'page arguments' => array('test_form',2),
            'access callback' => TRUE,
        ),
    );
    return $items;

    function test_form($form, &$form_state, $id=0) {
    
        $form['Title'] = array(
            '#title' => t('Title:'),
            '#type' => 'textfield',
            '#required' => TRUE,
            '#default_value' => $id,
        ); 

        return $form;
    
    }

Note: if you have more than one item in your URL then you need to adjust the number in your page arguments.
Also: you should add a default value to your wildcard argument or you may get errors/warnings if no argument is entered (though it should just give a 404)

blakefrederick’s picture

Yes this method works and your caveat is correct - you must include a default value for your wildcard argument or Drupal will error out.