5.x form.inc drupal_retrieve_form($form_id)
6.x form.inc drupal_retrieve_form($form_id, &$form_state)
7.x form.inc drupal_retrieve_form($form_id, &$form_state)

Retrieves the structured array that defines a given form.


$form_id: The unique string identifying the desired form. If a function with that name exists, it is called to build the form array. Modules that need to generate the same form (or very similar forms) using different $form_ids can implement hook_forms(), which maps different $form_id values to the proper form constructor function.

$form_state: A keyed array containing the current state of the form.

...: Any additional arguments needed by the unique form constructor function. Generally, these are any arguments passed into the drupal_get_form() or drupal_execute() functions after the first argument. If a module implements hook_forms(), it can examine these additional arguments and conditionally return different builder functions as well.

Related topics

2 string references to 'drupal_retrieve_form'
drupal_execute in includes/form.inc
Retrieves, populates, and processes a form.
drupal_rebuild_form in includes/form.inc
Retrieves a form, caches it and processes it with an empty $_POST.


includes/form.inc, line 375


function drupal_retrieve_form($form_id, &$form_state) {
  static $forms;

  // We save two copies of the incoming arguments: one for modules to use
  // when mapping form ids to constructor functions, and another to pass to
  // the constructor function itself. We shift out the first argument -- the
  // $form_id itself -- from the list to pass into the constructor function,
  // since it's already known.
  $args = func_get_args();
  $saved_args = $args;
  if (isset($form_state)) {

  // We first check to see if there's a function named after the $form_id.
  // If there is, we simply pass the arguments on to it to get the form.
  if (!function_exists($form_id)) {

    // In cases where many form_ids need to share a central constructor function,
    // such as the node editing form, modules can implement hook_forms(). It
    // maps one or more form_ids to the correct constructor functions.
    // We cache the results of that hook to save time, but that only works
    // for modules that know all their form_ids in advance. (A module that
    // adds a small 'rate this comment' form to each comment in a list
    // would need a unique form_id for each one, for example.)
    // So, we call the hook if $forms isn't yet populated, OR if it doesn't
    // yet have an entry for the requested form_id.
    if (!isset($forms) || !isset($forms[$form_id])) {
      $forms = module_invoke_all('forms', $form_id, $args);
    $form_definition = $forms[$form_id];
    if (isset($form_definition['callback arguments'])) {
      $args = array_merge($form_definition['callback arguments'], $args);
    if (isset($form_definition['callback'])) {
      $callback = $form_definition['callback'];
  array_unshift($args, NULL);
  $args[0] =& $form_state;

  // If $callback was returned by a hook_forms() implementation, call it.
  // Otherwise, call the function named after the form id.
  $form = call_user_func_array(isset($callback) ? $callback : $form_id, $args);

  // We store the original function arguments, rather than the final $arg
  // value, so that form_alter functions can see what was originally
  // passed to drupal_retrieve_form(). This allows the contents of #parameters
  // to be saved and passed in at a later date to recreate the form.
  $form['#parameters'] = $saved_args;
  return $form;


joe casey’s picture

The user_login form function (in user.module) contains this:

  // If we are already logged on, go to the user page instead.
  if ($user->uid) {
   drupal_goto('user/'. $user->uid);

So, if your module has a call like:
$form = drupal_retrieve_form('user_login');
the call will not return and you will instead get your user page.

I don't know if this happens for any other forms besides user_login.

In my opinion, the already-logged-on test should be left to the caller.

wortell’s picture

Ran into the same issue, but one could *for my app i'm considering it* check the http response to see if it was redirected - especially if it's based on a requested form via ajax, etc... just a thought :).