#native_company# #native_desc#
#native_cta#

automatic form generator

By marc daly
on July 7, 2007

Version: 1.2001

Type: Function

Category: Databases

License: GNU General Public License

Description: a function to display a form to insert values into a database table, automatically generating the form from the table, without the programmer explicitly have to name every field. Other options include default values, hiding fields and more. Fully commented(ish!) Insertable into your own pages completely transparently.

<?
/*
Version 1.01 - May 29, 2003 - 00:24 hours

------------------  WHAT DOES IT DO? ---------------------------
This function implements a generic submit structure for any table in a database, and will display a form on your page to allow the user to enter data and submit it to the database.

------------------ BUT MORE SPECIFICALLY, WHAT DOES IT DO? ----------------------------
1. It will fetch the fieldnames and field types for the specified table, including those that 
are autoincrement and should not user editable.

2. You can also specify any fields that are maintained by the database, such as might have default values
set in the table definition for instance.

3 The FOUR normal fields are :
--- tablename : the name of the table to insert form results into, cannot be ""
--- tableStyle :  a style snippet to identify the style of the table, can be ""
--- editStyle : a style snippet to determine what the editbox in the form will look like.				
--- fieldStyle : same as above, a style snippet to determine what the display name before each editbox will look like.
--- The style snippet can be a css style class defined in a stylesheet or inline on the page. This can also be given no value, as an empty set of quotes, or written as a style=value pair
--- For example, any of these is valid for the style snippet:
				1. "class=someCSSclass"
				2. "style='color:navy'"
				3. ""
				
				NB: Note the nesting of single quotes within the double quotes in example 2
			
--- These 4 default arguments cannot be ommitted, but only tablename needs a value.

4. You can specify name=value pairs for any fields in the table you are inserting into, simply append them as arguments to the function call.

--- An extra argument might be "creatorID=1" for instance, which will be written as a hidden form field, and also means the editbox for that field will not be displayed. This is useful if certain values are being obtained programmatically or from another page.

--- The extra arguments are specified as extra function arguments after the normal default four, in the form  "name1=value1", "name2=value2", "name3=FALSE", ..

--- When a field is given the value FALSE, it will not be displayed. This is handy if a field has a default value set in the table description and does not need to be entered explicitly by the user

--- You can also specify a number of choices for a field, from which the user can pick from a drop-down list or a radio group. If only two values are supplied for a field, then a radio group will be used, and a combo box otherwise. At its simplest these can be specified as so: "name1=value1,value2,value3,value4,..." You don't need to put quotes around the multiple values. You can include spaces to make your code more readable, the function will remove them during processing.

--- For arguments in the form "someField=a,b,c" you can also specify a separate display name and value to be used with the combo box or radio button group. Just write it in the form "someField=animal|a, box|b, carnival|c" The display name comes first, followed by the value. It is the value that will be inserted into the database. The display name is for the benefit of the user. Just separate them with the | characte.

--- Hard carriage returns entered in multi-line text boxes by the user at run-time are removed and replaced with the <br> tag to be more compatible with your database and operating system
		
-------------------- REQUIREMENTS ------------------------
5. Two variables need to be set in order fot the function to work

--- These are: $db - the link to the currently opened database and $dbName which is the name of the currently opened database
		
--- $db is the normal link variable name given to a database connection, so you'll probalby have that already, and the $dbName is just the name you use in your connection string and just needs to be defined explicitly. Of course your connection code or included file needs to be BEFORE this function page is included in your HTML page
		  
-------------------- USAGE -------------------------------
6. Just include this file in your HTML page where you want it to appear, using the 'include' directive, as in :   include "generic-submit.php"
		
--- This file doesn't reference any external files, so you can put it anywhere in relation to your directory structure and it should be ok.
			
--- To call the function in your code, write the following AFTER the point in your HTML page where you have INCLUDEd this file:
			
			genericSubmit ($tablename, $tableStyle, $editStyle, $fieldNameStyle [, ... , ... , ...] )
			
--- All arguments should be enclosed in quotes!
			
--- You can add as many arguments after the 4 default as you need to meet your requirements.
			
--------------------- IMPORTANT NOTE --------------------------
7. After you have read these comments and understand how to use the function, you should copy the file to keep a backup version, then remove all the comments from the original, to reduce the file size

------------------------ COPYRIGHT -----------------------------
8. Nuts to that! If you make any alterations and you think they're useful, send me a copy at [email protected] (www.cerebis.com) otherwise alter and abuse as you will.

--- As mentioned above in the IMPORTANT NOTE, you also definitely DO NOT need to include these comments in the production version!

--- Marc Daly, Waterford, Ireland (created May 27/28, 2003)

-------------------------- PROBLEMS ------------------------------
9. Send any error reports to [email protected] and I'll do my best to fix them immediately! Really.

--------------------------------------- TO DO -------------------------------------
10a. Include the ability to use an SQL statement to fill combo-box or radio group, instead of explicitly entering them when calling the function. I already have the combo-box code written elsewhere, it's just a case of working it in.

10b. Give the programmer an option to choose which of the multiple values they provide is to be the default choice, in either the radio group or as the selected choice in the combo box

11. Clean input from the user before the data is submitted to a database, remove quotes, newlines, etc.

12. Enforce data typing. If a field is set as a number type, allow only digits, show template for data/time, and so on

13. Provide option for tool tip type hints on each field, to give help to the user when entering data.
*/

function genericSubmit ($tablename, $tableStyle, $editStyle, $fieldNameStyle)
	{
	global $db, $dbName;
	$fields = mysql_list_fields($dbName, $tablename, $db); 	
	$columns = mysql_num_fields($fields); 

	// Using variable args to collect fields that need to be filled with pre-existing values,
	//  not entered by the user in edit boxes.
	$numArgs = func_num_args(); // check for extra variable arguments
	$argLoop = 4;  // known start of variable args
	while ($argLoop < $numArgs)  // fill an array with the variable args
		{
		$arg = func_get_arg ($argLoop);
		// Clean up the function args - Remove any spaces
		$arg = str_replace ( " ", "", $arg);
		// Seperate into name - value pairs and place in an array 'args'		
		list ($argName, $argValue) = explode ("=", $arg );
		$args[$argName] = $argValue;  // this is a PHP key => value pair array
		++$argLoop;
		}
	?>
<form name="myForm" method="get" action="">
<table <? echo ($tableStyle) ?>>
  <?
	$fieldLoop = 0;
	$actualColumns = 0;
	// Iterate through the fields in the table referred to in $tableName
	while ($fieldLoop < $columns)
		{
		$myFieldName = mysql_field_name ($fields, $fieldLoop);
		$fieldType = mysql_field_type($fields, $fieldLoop);
		// Define these here, as we will be using in possible 3 times in the following IF statements
		$autoIncrementState = strstr ( mysql_field_flags($fields, $fieldLoop), "auto_increment" );		
		$argPresetExists = isset ($args[$myFieldName]);
		// Set a prefix string for input element names to identify data type
		// Check for the data type of the field, and append the appropriate prefix to the name of the
		//   input element name, so that the do-gen-submit.php page will know whether to wrap quotes
		//   around the VALUE for this field in the INSERT statement
		if ( $fieldType == "blob" || $fieldType == "string" || $fieldType == "date" || $fieldType == "intdate")
			$typePrefix = "s_";
		else if ($fieldType == "int")
			$typePrefix = "i_";

		// - if value of a field was given as FALSE in that list, DON'T display it
		// - if a name/value pair was given for this field, write it as a hidden input element
		// - if an autoincrement type, which is up to the database to maintain, DON'T display it
		if ($autoIncrementState )  {} // don't display - it's an autoincrement field
	 // No value preset in the variable args list OR there are MULTIPLE values preset for this field, DISPLAY field as editbox or if MULTIPLE then combo box or radio group as appropriate
		else if (!$argPresetExists || @strstr ($args[$myFieldName], ",") )
		 	{
			++$actualColumns; // This is a count of table fields in the form, including hidden elements
?><tr><td <? echo $fieldNameStyle; ?>><? echo $myFieldName; ?></td><td><?
			// Check for multiple choices for a field, indicated by a comma in the value
			if ( @strstr ($args[$myFieldName], ",") )  // Does the current value contain a comma?
				{
				// If there is a comma, then there must be a list in the value, separate them out and write them to a radio group or combo box.
				$multipleChoice = explode (",", $args [$myFieldName] );
				// Now choose either a Radio group ot a Combo box, depending on the number of choices
				if (count ($multipleChoice) <= 2)
					{
					// place in a table
					echo "<table><tr>";
					foreach ($multipleChoice as $myChoice) // do a radio group
						{
						// Check for | character, indicates a display name and value for multiple choice item
						if (!strstr($myChoice, "|"))
							{
							echo "<td>" . $myChoice . "</td><td><input type='radio' name='" . $typePrefix . $myFieldName . "' value='" . $myChoice . "'></td><td width=15></td>";
							}
						else // the | character was found, so explode the string to get name and value
							{
							list ($elName, $elValue) = explode ("|", $myChoice);
							echo "<td>" . $elName . "</td><td><input type='radio' name='" . $typePrefix . $myFieldName . "' value='" . $elValue . "'></td><td width=15></td>";							
							}
						}
					echo "</tr></table>";
					}
				else	// do a Combo box
					{
					echo "<select name='" . $typePrefix . $myFieldName . "'>";
					foreach ($multipleChoice as $myChoice)
						{
						if (!strstr($myChoice, "|"))
							{
							echo "<option>" . $myChoice . "</option>";
							}
						else // the | character was found, so explode the string to get name and value
							{
							list ($elName, $elValue) = explode ("|", $myChoice);
							echo "<option value='" . $elValue . "'>" . $elName . "</option>";
							}
						}
					echo "</select>";
					}					
				}
			else
				echo ("<textarea " . $editStyle . " name='" . $typePrefix . $myFieldName . "'></textarea>");				
//				echo ("<input " . $editStyle . " type='text' name='" . $typePrefix . $myFieldName . "'>");
?></td></tr><?
  			}
		// this is a field we already have values for, from the variable arg's list
		else if ($argPresetExists && $args[$myFieldName] != "FALSE")
			{
			echo "<input type='hidden' name='";

			// Check for the data type of the field, and append the appropriate prefix to the name of the
			//   input element name, so that the do-gen-submit.php page will know whether to wrap quotes
			//   around the VALUE for this field in the INSERT statement
			echo ( $typePrefix );
			echo $myFieldName . "' value='" . $args[$myFieldName] . "'>";
			++$actualColumns;			
			}
			
		++$fieldLoop;
		}
?>

<tr><td><script language="JavaScript" type="text/JavaScript">
function doSubmit ()
	{
	myForm.pressedSubmit.value = "y";
	myForm.submit();
	}
</script>
		  <input name="tablename" type="hidden" id="myTablename" value="<? echo ($tablename); ?>">
<input name="numrows" type="hidden" id="tablename" value="<? echo ($actualColumns); ?>">
		  <input name="pressedSubmit" type="hidden" id="pressedSubmit"> </td>
		<td><input name="Submit" type="button" value="Submit" language="javascript" onclick="doSubmit()"></td></tr>
</table>
</form><br>

<?
}

	// -------------- DO THE INSERT WHEN THE FORM IS SUBMITTED ------------
if ( isset ($_GET ['pressedSubmit']) && $_GET ['pressedSubmit'] == "y" )
	{
	global $db, $dbName;
	$fieldValues = "";
	$fieldNames = "";	
	$fieldLoop = 0;
	foreach($_GET as $key => $value)
		{
		if ($fieldLoop < $_GET['numrows'])
			{
			if (substr ($key, 0, 2) == "s_")
				{
				$value = str_replace ( "n", "", $value);
				$value = str_replace ( "r", "<br>", $value);
				$fieldValues .= "'" . $value . "' , ";
				}
			else
				$fieldValues .= $value . " , ";
		
			++$fieldLoop;
			}
		}
		
	$fieldLoop = 0;
	foreach($_GET as $key => $value)
		{
		if ( $fieldLoop < $_GET['numrows'] )
			{
			$fieldNames .= substr($key, 2, strlen($key) - 2) . ", ";
			++$fieldLoop;
			}
		}

	$fieldNames = substr ($fieldNames, 0 , -2 );
	$fieldValues = substr ($fieldValues, 0 , -2 );	
	$temp = "INSERT INTO " . $_GET['tablename'] . " (" .$fieldNames . ") VALUES (" . $fieldValues . ")";

	echo ($temp); // uncomment this line to see the INSERT statement generated by the function
	// Do the INSERT
//	mysql_query($temp, $db);  // Remember $db is your database connection variable
	}
?>