| 5 form.inc | drupal_get_form($form_id) |
| 6 form.inc | drupal_get_form($form_id) |
| 7 form.inc | drupal_get_form($form_id) |
| 8 form.inc | drupal_get_form($form_id) |
Retrieves a form from a constructor function, or from the cache if the form was built in a previous page-load. The form is then passed on for processing, after and rendered for display if necessary.
Parameters
$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. Examples may be found in node_forms(), search_forms(), and user_forms().
...: Any additional arguments are passed on to the functions called by drupal_get_form(), including the unique form constructor function. For example, the node_edit form requires that a node object be passed in here when it is called. These are available to implementations of hook_form_alter() and hook_form_FORM_ID_alter() as the array $form['#parameters'].
Return value
The rendered form.
Related topics
File
- includes/
form.inc, line 70
Code
<?php
function drupal_get_form($form_id) {
$form_state = array(
'storage' => NULL,
'submitted' => FALSE,
);
$args = func_get_args();
$cacheable = FALSE;
if (isset($_SESSION['batch_form_state'])) {
// We've been redirected here after a batch processing : the form has
// already been processed, so we grab the post-process $form_state value
// and move on to form display. See _batch_finished() function.
$form_state = $_SESSION['batch_form_state'];
unset($_SESSION['batch_form_state']);
}
else {
// If the incoming $_POST contains a form_build_id, we'll check the
// cache for a copy of the form in question. If it's there, we don't
// have to rebuild the form to proceed. In addition, if there is stored
// form_state data from a previous step, we'll retrieve it so it can
// be passed on to the form processing code.
if (isset($_POST['form_id']) && $_POST['form_id'] == $form_id && !empty($_POST['form_build_id'])) {
$form = form_get_cache($_POST['form_build_id'], $form_state);
}
// If the previous bit of code didn't result in a populated $form
// object, we're hitting the form for the first time and we need
// to build it from scratch.
if (!isset($form)) {
$form_state['post'] = $_POST;
// Use a copy of the function's arguments for manipulation
$args_temp = $args;
$args_temp[0] = &$form_state;
array_unshift($args_temp, $form_id);
$form = call_user_func_array('drupal_retrieve_form', $args_temp);
$form_build_id = 'form-' . md5(uniqid(mt_rand(), TRUE));
$form['#build_id'] = $form_build_id;
drupal_prepare_form($form_id, $form, $form_state);
// Store a copy of the unprocessed form for caching and indicate that it
// is cacheable if #cache will be set.
$original_form = $form;
$cacheable = TRUE;
unset($form_state['post']);
}
$form['#post'] = $_POST;
// Now that we know we have a form, we'll process it (validating,
// submitting, and handling the results returned by its submission
// handlers. Submit handlers accumulate data in the form_state by
// altering the $form_state variable, which is passed into them by
// reference.
drupal_process_form($form_id, $form, $form_state);
if ($cacheable && !empty($form['#cache'])) {
// Caching is done past drupal_process_form so #process callbacks can
// set #cache.
form_set_cache($form_build_id, $original_form, $form_state);
}
}
// Most simple, single-step forms will be finished by this point --
// drupal_process_form() usually redirects to another page (or to
// a 'fresh' copy of the form) once processing is complete. If one
// of the form's handlers has set $form_state['redirect'] to FALSE,
// the form will simply be re-rendered with the values still in its
// fields.
//
// If $form_state['storage'] or $form_state['rebuild'] has been set
// and input has been processed, we know that we're in a complex
// multi-part process of some sort and the form's workflow is NOT
// complete. We need to construct a fresh copy of the form, passing
// in the latest $form_state in addition to any other variables passed
// into drupal_get_form().
if ((!empty($form_state['storage']) || !empty($form_state['rebuild'])) && !empty($form_state['process_input']) && !form_get_errors()) {
$form = drupal_rebuild_form($form_id, $form_state, $args);
}
// If we haven't redirected to a new location by now, we want to
// render whatever form array is currently in hand.
return drupal_render_form($form_id, $form);
}
?> Login or register to post comments
Comments
Snippet for returning a node form
To get a node edit form, you need to include node.pages.inc.
<?php// required for Drupal 6
module_load_include('inc', 'node', 'node.pages');
// which nodeform you want
$node_type = 'YOURNODETYPE';
$form_id = $node_type . '_node_form';
// maybe add current users info
global $user;
// create a blank node
$node = array(
'uid' => $user->uid,
'name' => (isset($user->name) ? $user->name : ''),
'type' => $node_type,
);
// Invoke hook_nodapi and hook_node
node_object_prepare($node);
// Or you can also use an exiting node, for example
// $node = node_load(123);
// and the display the form:
$output = drupal_get_form($form_id, $node);
?>
Your comment was very helpful
However, the node_object_prepare() function takes an object (as the name implies), and your $node is an array.
Something like
<?php$node->uid = $user->uid;
$node->name = (isset($user->name) ? $user->name : '');
$node->type = $node_type;
?>
instead of
<?php$node = array(
'uid' => $user->uid,
'name' => (isset($user->name) ? $user->name : ''),
'type' => $node_type,
);
?>
would be better.
FYI - AFAIK - you can pass additional arguments to this func..
if the form you're asking for requires them... (I'm using Drupal 6.15)
took me a while to figure this out... maybe it'll help someone else.
HEre's an example with the watcher module that I'm using successfully...
module_load_include('inc', 'watcher', 'watcher.db');global $user;
print drupal_get_form('_watcher_user_settings', $user );
where I'm passing the $user to the function. Looking at the function (from watcher.module)
function _watcher_user_settings(&$form_state, $account) {// ... super usefull code here - thx author!!!
}
we can see that it is expecting an argument ' $account ' ( a user object ). If I fail to pass the argument as listed in the first code segment, I get errors.
Hope this helps someone...
-Supertwang
To get rid of the errors, I
To get rid of the errors, I think you just have to declare the $account variable in the function. If you include it, your array will override the empty one.
<?phpfunction _watcher_user_settings(&$form_state, $account = array()) {
// ... super usefull code here - thx author!!!
}
?>
Extra Arguments Confusion
You can call this function without extra arguments like so:
drupal_get_form('module_form');
function module_form() {
// whatever
}
Notice that module_form() does not have any arguments.
If you need an extra argument like so:
drupal_get_form('module_form', $extra_arg);
function module_form(&$form_state, $extra_arg) {
// whatever
}
Notice that module_form() must add &$form_state and then $extra_arg.
This is an essential note
I lost an afternoon (and the noon) trying to figure out why my form doesn't contain $node object (when created with drupal_get_form), .
So i think this is reasonable mistake (having in mind drupal 5.x functionality) and this comment has to become a link where ever the drupal_get_form is applied on documentation. That will save afternoons from a lot of people, investigating possible (syntax) errors . I'm sure!
Thank you, thank you, thank you!!!
All of you who are learning drupal by the Pro Drupal Development from Apress beware of the mistake in the source code from the second chapter.
When you call your annotate_entry_form() function remember to use the method Scott McCabe described above:
function annotate_entry_form(&$form_state, $node) {// Your code goes here and you will have an access to those
// $node->annotation and $node->nid values at last!
}
I have spent hours fighting it!!! Thank you very much!
Extra Arguments in D7
For D7, the argument is now in a new array.
function module_form(&$form_state, $extra_arg) {// whatever
}
Instead of calling $extra_arg directly (like in D6), it's now $extra_arg['build_info']['args'][0]
Will call registered theme functions
I'm working on submitting a patch to an existing module, and this module has a theme function that was being called, but I couldn't figure out where in the world it was being called from. I found my answer in this function.
You'll notice in the code above that
drupal_get_formreturnsreturn drupal_render_form($form_id, $form);. You can track down drupal_render_form in form.inc. That function adds the #theme callback to the form array if the #theme callback is registered but not already set in the current form array. (It might be already set if the theme function was being overridden by some *other* module). In this case, however, the module I want to patch *had* registered the theme function, but had not added it to the form array yet. The #theme callback is added in this step, and so the theme function from my module gets called from drupal_render. Mystery solved.