Article #1007: Reducing SQL Modifications When Changing Form Data

 

The modification of Web forms is a three step process. The form itself is modified, and so to are the database procedures that insert or update records (our focus for automation) in conjunction to the modification of actual database table fields. Changes normally involve renaming, adding or removing form input controls and their associated reference names on a Web page and matching fields in database table(s). We can eliminate the often overlooked step of reflecting changes to our SQL statements in the source code after adjusting the form interface and database structure. The tedious task of adjusting the form's (behind the scenes) data storage procedure via SQL can become automated. The modification of SQL statements to transfer form input data into corresponding database records is self-adjusting. Through the use of a form input control naming convention -- manual SQL statement modifications pertaining to the INSERT and UPDATE procedures are eliminated via a generic form update handler. Believe it or not, this organized script will reduce development time whenever a form is updated to reflect new or different fields of information. The generic routine below is beneficial to large evolving projects with continuous structural changes that require modifications to forms and the storage of their associated input data using SQL. Adjusting the UI aspect of a form and forgetting to accommodate for the data storage procedure is no longer an overlooked debugging issue. The routine below automates this process as long as the form input controls on a Web page adhere to a convenient naming convention.

The form control naming convention helps the function: form_update_data() identify a means by which to generate a valid SQL statement, and without manual intervention. The form control naming convention: ([...] optional constituent)

Record Update or Insert (pre-determined key):
tableAcronym_correspondingTableFieldName_id[recordID]

Record Insert (database assigned key, i.e. auto increment key):
tableAcronym_correspondingTableFieldName_id[symbol+index]

The first parameter of the function call to form_update_data ($conv_id, $input, $ins, $num = true, $sql_escape = ESC_MSSQL, &$sql_vals = NULL); is the table identifier acronym, which will indicate which matching form data corresponds to the associated table. In the example below, "itm" would be table item. The second parameter is the passing of an array containing the source data so a form would require the POST ($_POST) array. The third parameter is an indication of either an INSERT or UPDATE (true or false) operation. This is determined by your calling script perhaps by a database record look-up for an existing record. The INSERT operation can be replaced by the REPLACE command if preferred, and may deem a pre-existing record look-up unnecessary. The indication will default to INSERT for auto database assigned keys. The forth parameter, when set to true, will avoid encompassing numeric values (hexadecimal, integer, float, etc.) by single quotes, which would generate an error in MSSQL for numeric fields. Set this parameter for MSSQL and clear it for MySQL. The last parameter takes a pass-by-reference array that will contain the actual values contained within the form controls or array source.

Eg. (item_name and item_cost field values for an existing record of ID 11237)
<input type = 'text' name = 'itm_item_name_id11237' value = 'Bolt'>
<input type = 'text' name = 'itm_item_cost_id11237' value = '0.20'>

Eg. (item_name and item_cost field values for a new record, no ID)
<input type = 'text' name = 'itm_item_name_id' value = 'Washer'>
<input type = 'text' name = 'itm_item_cost_id' value = '0.10'>

Eg. (item_name and item_cost field values for multiple new records, no ID)
<input type = 'text' name = 'itm_item_name_idi0' value = 'Washer'>
<input type = 'text' name = 'itm_item_cost_idi0' value = '0.10'>
<input type = 'text' name = 'itm_item_name_idi1' value = 'Bolt'>
<input type = 'text' name = 'itm_item_cost_idi1' value = '0.20'>

<?

  // record insertion symbol for auto assigned DB record ID
define ("INS_SYMBOL", "i");
define ("ESC_MSSQL", "1"); // escape MSSQL values
define ("ESC_MYSQL", "2"); // escape MYSQL values

// condense code associated with changing SQL statements when
// database storage of changing form control data output occurs
function form_update_data ($conv_id, $input, $ins, $num = true,
      $sql_escape = ESC_MSSQL, &$sql_vals = NULL)
{ // table acronym identifier, array of fields,
  // record insertion (true) or update (false),
  // surround numeric values with quotes '' (mssql),
  // ESC_MSSQL = mssql escape apostrophe (''),
  // ESC_MYSQL = mysql escape w/ addslashes (\'), 0 = no escape
  // array to be filled with actual record field values
  $quote = "'";
  // sql fragment containing specific field assignments
  $sql_frag = array ();
  $ins_orig = $ins;
  foreach ($input as $shortnm => $val)
  {
    $ins = $ins_orig;
    if ($sql_escape == ESC_MSSQL) // mssql escaped apostrophe
      $val = str_replace ("'", "''", $val);
    else if ($sql_escape == ESC_MYSQL) // mysql escaped apostrophe
      $val = addslashes ($val);
    // find the specific data according to convention ID
    if (preg_match ("/^($conv_id)_(.*)_id(.*){0,1}/i", $shortnm, $matches))
    {
      if (!$matches[1])
        continue;
      if ($matches[3][0] == INS_SYMBOL) // force insert (new record)
        $ins = true;
      $id = $matches[3] ? $matches[3] : 0;
      if ($ins) // INSERT
      { // field & value clauses
        $sql_frag[$id][0] .= ($sql_frag[$id][0] != "" ? ", " : "");
        $sql_frag[$id][1] .= ($sql_frag[$id][1] != "" ? ", " : "");
      }
      else // UPDATE
        $sql_frag[$id] .= ($sql_frag[$id] != "" ? ", " : "");
      if ($num) // exclude quotes from numeric values (MSSQL)
        $quote = (is_numeric ($val) ? "" : "'");
      if ($ins) // INSERT
      {
        $sql_frag[$id][0] .= $matches[2]; // field clause
        $sql_frag[$id][1] .= $quote.$val.$quote; // value clause
      }
      else // UPDATE
        $sql_frag[$id] .= "$matches[2] = ".$quote.$val.$quote;
      $sql_vals[$id][] = $val;
    }
  }
  return $sql_frag;
}

?>

Code View - dynamicreport.com


<?

// place this code anywhere in your save form data procedure
$ins = false; // figure out if this is an insert or update procedure
$sql_vals = array (); // array will store actual SQL values

$sql_frag = form_update_data ("itm", $_POST, $ins, true, ESC_MSSQL, $sql_vals);
$table = "items";
$fld_id = "item_id";
// cycle through all form data pertaining to a table
foreach ($sql_frag as $id => $val)
{
  if ($id[0] == INS_SYMBOL)
  { // insertion of new records (auto database assigned key)
    if ($sql_vals[$id][0] == "")
      continue; // handle the 1st blank field, skip record
    $sql = "INSERT INTO $table (".$sql_frag[$id][0].") ".
      "VALUES (".$sql_frag[$id][1].")";
  }
  else
  { // update existing record, but delete it if essential field(s) are blank
    if ($sql_vals[$id][0] == "") // handle 1st blank field, delete record 1st
      $sql = "DELETE FROM $table WHERE $fld_id = '$id'";
    else
      $sql = "UPDATE $table SET $sql_frag[$id] WHERE $fld_id = '$id'";
  }
  mssql_query ($sql); // execute the auto-generated database record query
}


?>

Code View - dynamicreport.com

There is no need to modify the SQL insert/update procedure above when adding a new source array element or Web page form control. The generic procedure above will work as long as array elements or form controls use the naming convention discussed.

 
 

Back to article listing

 


 

Copyright © 2007-2008 Interaxis. All rights reserved.
Contact Webmaster