kludge to reuse form/table builder functions with TAPIR theme

Posts: 24
Joined: 02/28/2008

If anyone has a better way to do this, please let me know. If anyone find it useful, then it's great.

Based on my understanding, the standard way to theme a form using TAPIR is as following
(see http://www.ubercart.org/docs/tapir/3000/example_6_theme_form_tapir)

<?php
// main code to call drupal form
drupal_get_form('tapirtest_example_6_form');
...

function
theme_tapirtest_example_6_form($form) {
 
$output = '<p>'. tapir_get_table('tapirtest_example_table_6', $form)
          .
drupal_render($form['submit']) .'</p>'; // add submit button, not the whole form
 
return $output;
}

// form builder function
function tapirtest_example_6_form() // I want to reuse this function with different parameters
{
 
$form['songs'] = array('#tree' => TRUE);
 
$result = db_query("SELECT * FROM {tapirtest_example_5}"); // I want to add parameters in sql string
 
while ($row = db_fetch_object($result)) {
   
$form['songs'][$row->song_id]['song'] = array(
  ...
}

// table builder function
function tapirtest_example_table_6($op, $form) {
  switch (
$op) {
    case
'fields':
     
$fields[] = array('name' => 'song', 'title' => t('Song'), 'weight' => 0, 'enabled' => TRUE);
...
}
?>

What I want to do is to reuse the form builder function with parameters. I'd prefer to pass the parameters from drupal_get_form() to the form builder function, I couldn't find a way to do it, so I added extra hard coded function names, then these functions call the form builder with the parameters.
It looked really stupid, but I can reuse the form builder, and table builder.

<?php
  
// get artist john
  
drupal_get_form('artist_john_form');

  
// get artist jane
  
drupal_get_form('artist_jane_form');

function
theme_artist_john_form($form) {

 
$output = '<p>'. tapir_get_table('tapirtest_example_table_6', $form)
          .
drupal_render($form['submit']) .'</p>';
  return
$output;
}
function
artist_john_form()
{
  return
tapirtest_example_6_form('john');
}  

function
theme_artist_jane_form($form) {

 
$output = '<p>'. tapir_get_table('tapirtest_example_table_6', $form)
          .
drupal_render($form['submit']) .'</p>';
  return
$output;
}

function
artist_jane_form()
{
  return
tapirtest_example_6_form('jane');
}  

// form builder function
function tapirtest_example_6_form($artist='') // added one parameter
{
 
$where = "";
  if (
$artist != '')
   
$where = " where artist ='".$artist."'";

 
$form['songs'] = array('#tree' => TRUE);
 
$result = db_query("SELECT * FROM {tapirtest_example_5} ".$where); // find the artist
 
while ($row = db_fetch_object($result)) {
   
$form['songs'][$row->song_id]['song'] = array(
  ...
}
// table builder unchanged
?>

The limit is that you can only add a few functions with parameters you already know in advance.

Posts: 24
Joined: 02/28/2008

The limit is that you can only add a few functions with parameters that you already know in advance.

Posts: 5617
Joined: 08/07/2007
AdministratorHead Code Monkey - I eat bugs.

A few things, and I'll help you clean up the code per Drupal's coding standards:

1) With drupal_get_form(), you can supply as many arguments as you need:

<?php
  drupal_get_form
('tapirtest_example_6_form', 'john');
?>

Now 'john' will be passed in as $artist.

2) You have to protect your SQL statements using what's called Drupal's database abstraction layer:

<?php
/**
* A modified version of your form builder function.
* Note that I'm not exactly sure how you intend to use this form, but I'm just
* going to assume we're getting a value in $artist.
*/
function tapirtest_example_6_form($artist = '') {
 
$form['songs'] = array('#tree' => TRUE);

  if (!empty(
$artist)) {
   
$result = db_query("SELECT * FROM {tapirtest_example_5} WHERE artist = '%s'", $artist);
    while (
$row = db_fetch_object($result)) {
     
$form['songs'][$row->song_id]['song'] = array(
        ...
      );
    }
  }
  ...
  return
$form;
}
?>

Notice that db_query() uses printf style replacement where %s denotes a string, %d an integer, and %f a float. Arguments are listed either as arguments in the function call itself or with an array as the second argument.

Also, watch your function brackets and string concatenation placement.

Hope this helps!

Posts: 24
Joined: 02/28/2008

I can't say enough thank you for what you guys did!

Having played Tapir for only 2 days, I am totally blown away by the power and simplicity of this Tapir thingy. It's incredible!

Can I beg two more questions:

1. I am an amateur PHP guy, so even if drupal_get_form($form_id) signature indicates only one parameter, you can still pass in more?

2. On the dynamic Tapir table, I see alter function can add new fields. Is there a call that allows me to turn on/off fields on the fly as I re-use the table multiple times on the same page? e.g. when I call the table the first time, I have 'artist' column, when I call it 2nd time on the same page, it doesn't show 'artist' column?

BTW, I am re-coding my program using Tapir to replace the "views" I created before. I found Tapir so powerful, which gives me all the flexibility. I also believe I can improve the performances, because I can fine tuning my db queries.

Posts: 5617
Joined: 08/07/2007
AdministratorHead Code Monkey - I eat bugs.

Just to provide a warning, there are limitations to TAPIr that I know about now that I wish I had known when I made the module. You might find it difficult to work in some table_alters, particularly if you're an amateur PHP guy.

Regarding the drupal_get_form() function, yep you can pass in as many arguments as you want. This is a feature of PHP. If you look at the API page for that func that I linked you to, you'll see a ... in the arguments list that represents as many optional arguments as you want to pass in for that function. It uses func_get_args() to figure out what it was you passed in and then pass those on to the form builder as arguments.