Ok, I am programming a website and I need to do a lot of html forms everywhere. How can I reduce amount of my time doing that? Any ideas? I guess it should be done with functions.
I don't use neither any frameworks nor OOP yet.
Thank you very much.
Please google "Zen Coding". I think it is what you want. For example:
If you input div#content>h1+p , the following html will be generated:
<div id="content">
<h1></h1>
<p></p>
</div>
Zen Coding is supported by a lot of editors.
Unfortunately, there is no magic FormBuilder::readMyMind() function yet, so you will spend some time on it. Here is some FormBuilders you can use without having to use a framework:
http://pear.php.net/package/HTML_QuickForm2
http://pear.php.net/package/DB_DataObject_FormBuilder
http://framework.zend.com/manual/en/zend.form.html
Note that Zend_Form is part of Zend Framework, but can be used standalone. It does have a number of dependencies on other ZF components though.
My suggestion is to start using a framework sooner as you'll find a lot of your work is already done for you. CodeIgniter or Zend aren't bad ones. If not I'd write a few classes myself that given a number of parameters can render the html needed. Personally getting a framework is a much more compelling choice in the long run.
May be have a look at
http://pear.php.net/package/HTML_QuickForm2
The greater the abstraction (the easier it is to use) then the less control your going to have over the final output. So it may depend on how complex your forms are going to be that will determine the tools you can use.
I wrote a small class to to create a form based on a DB table, a few years ago.
Here is a method to grab all the fields & field types from a database table:
public function getDatabaseFields($db_name, $tbl, $ignoredFields)
{
$db = mysqli_select_db($this->connect, $db_name);
$sql = "DESCRIBE $tbl";
$result = mysqli_query($this->connect, $sql);
if ($result !== false)
{
$i = 0;
while ($row = mysqli_fetch_array($result, MYSQL_ASSOC))
{
if (!in_array($row[Field], $ignoredFields))
{
$formItems[$i][lbl] = $row[Field];
$formItems[$i][type] = $row[Type];
$formItems[$i][nul] = $row["Null"];
}
$i++;
}
return $formItems;
}
else
{
return false;
}
}
And here is a method to generate forms based on that data:
/**
* This function gets the details of a table and
* creates a form to insert values in that table
* $ignoredFields is an array of fields which should not be in the form
* $specialFields contain complete fields ready to output, (useful if you need fields not in the table)
* $existingData are data that should be displayed in the fields
* $options[formTitle] displays a title above the form in a separate <div>
* $options[errors][fieldName] display the field's label in bold red letters
* $options[hidden][fieldName] set field as hidden and the value is $options[hidden][fieldName][value]
* #param <string> $db_name
* #param <string> $tbl
* #param <array> $ignoredFields
* #param <array> $specialFields
* #param <array> $existingData
* #param <array> $options
*/
function form_db_table($db_name, $tbl, $ignoredFields, $specialFields, $existingData, $options)
{
# Get all the database fields that must be filled out.
$formItems = $this->getDatabaseFields($db_name, $tbl, $ignoredFields);
# Generate the form fields and load them in variables
foreach ($formItems as $key=>$value)
{
# $fieldName is the actual field name in the database.
# $fieldLbl is the name displayed in the form before the field
$fieldName = $value[lbl];
$pattern = array('/([a-z])([A-Z])/','/[_-]/');
$replacement = array('$1 $2', ' ');
$fieldLbl = ucfirst(strtolower(preg_replace($pattern, $replacement, $fieldName)));
# if $fieldName is in $options[hidden], an hidden input is created
if (is_array($options[hidden]))
{
if (array_key_exists($fieldName, $options[hidden]))
{
$val = $options[hidden][$fieldName];
$formEntries .= "<input type='hidden' name='$fieldName' value='$val' />";
continue;
}
}
if($value[nul] == "YES")
{
$mandatory = "";
}
else
{
$mandatory = "*";
$mandatoryFields .= $value[lbl] . ";";
}
// from type, decide which form item to use: varchar = <input> ...
if (stripos($value[type],"varchar") !== false)
{
$varcharLimit = substr($value[type], 8, -1);
if ($varcharLimit < 71)
{
$inputItem = "<input type=\"text\" size=\"38\" maxlength=\"$varcharLimit\"".
" name=\"$fieldName\" value=\"$existingData[$fieldName]\" class=\"entryField\"/>";
}
else
{
$inputItem = "<textarea cols=\"35\" rows=\"3\" wrap=\"VIRTUAL\"" .
" name=\"$fieldName\" class=\"entryField\">$existingData[$fieldName]</textarea>";
}
}
else if (stripos($value[type],"text") !== false)
{
$inputItem = "<textarea cols=\"35\" rows=\"8\" wrap=\"VIRTUAL\"" .
" name=\"$fieldName\" class=\"entryField\">$existingData[$fieldName]</textarea>";
}
else if (stripos($value[type],"date") !== false)
{
$inputItem = "<input type=\"text\" size=\"38\" maxlength=\"50\"".
" name=\"$fieldName\" value=\"$existingData[$fieldName]\" class=\"entryField\"/>";
}
else if (stripos($value[type],"enum") !== false)
{
$inputItem = "<select size=\"1\" name=\"$fieldName\">\r\n";
if (isset($existingData[$fieldName]))
{
$inputItem .= "<option value=\"$existingData[$fieldName]\">$existingData[$fieldName]</option>";
}
$enumVal = explode(",",substr($value[type], 6, -1));
foreach($enumVal as $key => $value)
{
$val= trim(str_replace("'", "", $value));
$inputItem .= "<option value=\"$val\">$val</option>";
}
$inputItem .= "</select>";
}
## !!! COMPLETE THE LIST OF TYPES !!!
$error = $options[error][$fieldName];
$formEntries .= "<div class=\"entry\">\r\n";
$formEntries .= "<label class=\"lbl_regular\" style=\"$error\">\r\n";
$formEntries .= "$fieldLbl$mandatory</label>\r\n$inputItem \r\n";
$formEntries .= "</div>\r\n";
}
# Sends the list of mandatory fields
if ($mandatoryFields != "")
{
$mandatoryFields = substr($mandatoryFields, 0, -1);
//- Explode to determine which fields can't be blank -\\
$mandatoryFields = "<input type='hidden' name='mandatory' value='$mandatoryFields'>\r\n";
}
# Extract special fields - fields and labels ready for output
if (is_array($specialFields))
{
foreach ($specialFields as $key=>$value)
{
if($value[where]="before")
{
$specFieldsBefore .= "$value[openField] $value[lbl] $value[field]\r\n $value[closeField] \r\n";
}
else
{
$specFieldsAfter .= "$value[openField] $value[lbl] $value[field]\r\n $value[closeField] \r\n";
}
}
}
# Error message
if (isset($options[errMsg]))
{
echo "<div class=\"errorMsg\">$options[errMsg]</div>";
}
# Output the top of the form
echo $this->formTag;
if (isset($options[formTitle]))
{
echo "\r\n<div class=\"formTitle\">$options[formTitle]</div>\r\n";
}
echo "<fieldset class=\"formFieldSet\">\r\n";
#output the the actual fields
echo $mandatoryFields;
echo $specFieldsBefore;
echo $formEntries;
echo $specFieldsAfter;
# Close fieldset, add a validate button and close the form
echo "</fieldset>";
echo "<center><input type=\"submit\" value=\"Submit\" name=\"submit\" /></center>";
echo "</form>";
}
No doubt there must be more elegant solutions out there, but if the form's purpose is to fill out a database table, it makes it pretty easy to generate a form.
Related
I have 2 pieces of code from a simple plugin that work independently from each other but don't work together.
if(isset($_POST['submit'])){
if(has_presence($_POST['product_name'])){
insert_row_into_table('CAL_products');
show_errors();
if(has_presence($wpdb->last_query)) {
echo "Update Successful";
} else {
echo "Update Failed";
}
} else {
echo "The field 'Product Name' cannot be blank.";
}
}
And this one
$results_array = $wpdb->get_results("SELECT * FROM wpCMS_CAL_products ORDER BY id ASC");
echo build_table_from_results_array($results_array);
The functions are included at the bottom.
The problem I have is that when the page loads there is no $_POST so it skips over the if statement and builds the table. This table builds fine.
When the form is submitted the if statements come back true and the new value is added to the database successfully, but then the table doesn't build until the page is refreshed. If the code to build the table is put at the top above the if statement it builds fine but doesn't include the new value until the page is refreshed.
Is it possible to add a new item to the database table before the results are populated to the HTML table?
function insert_row_into_table($table_name){
global $wpdb;
$prefix = $wpdb->prefix; //Define the wordpress table prefix
$table = $prefix . $table_name; //Build the table name
unset($_POST['submit']);
echo print_r($_POST);
$data = $_POST; //collect the data from post
$wpdb->insert( $table, $data ); //insert data into the table
}
function show_errors(){
echo $wpdb->show_errors();
echo $wpdb->print_error();
}
function has_presence($value) {
return isset($value) && $value !== "";
}
function build_table_from_results_array($results_array) {
$out = "";
$out .= "<table class=\"widefat\">";
$out .= "<thead>";
foreach($results_array[0] as $key => $element) {
if($key == "id") {
$out .= "<th class=\"id-column\">";
$out .= strtoupper($key);
$out .= "</th>";
} else {
$out .= "<th>";
$out .= ucwords(str_replace("_", " ", $key));
$out .= "</th>";
}
}
$out .= "</thead>";
$out .= "<tbody>";
$i = 0;
foreach($results_array as $key => $element){
if($i % 2 === 0) $extraclass= "alternate";
$out .= "<tr class=\"$extraclass\">";
$i++;
$extraclass="";
foreach($element as $subkey => $subelement){
$out .= "<td>$subelement</td>";
}
$out .= "<td>EDIT</td>";
$out .= "</tr>";
}
$out .= "</tbody>";
$out .= "</table>";
return $out;
}
A general pattern for this type of page is Post-Redirect-Get. You could, for instance, pull the if(isset($_POST['submit'])) block out into a separate file called processForm.php. The form's action parameter is changed to processForm.php. The form sends $_POST data to processForm which inserts the new database records, and processForm in turn redirects the user back to the original page which gets the results.
If you want a one-page solution using the above code, add this code at the very top of the file, before you output anything at all. This starts the output buffer, which is usually necessary if you want to use the header() command to redirect.
ob_start();
Then edit the if(isset) block:
if(isset($_POST['submit'])){
if(has_presence($_POST['product_name'])){
insert_row_into_table('CAL_products');
show_errors();
if(has_presence($wpdb->last_query)) {
echo "Update Successful";
header("Location: index.php"); //change index.php to the current page
//header("Location: ".$from); //or use a variable
} else {
echo "Update Failed";
}
} else {
echo "The field 'Product Name' cannot be blank.";
}
}
Finally, add this at the very end of the script to close the output buffer:
ob_end_flush();
Essentially, this code refreshes the page on success after the new entries are inserted into the database. This should allow your table to include the new records.
Following is an ajax post page which renders the checkboxes on run-time. I am facing issue while writting the script for select all button, when I click on the button only 1 value is getting selected not the entire array:
<?php
session_start();
error_reporting(E_ALL);
ini_set("display_errors", 1);
include("../includes/functions.php");
if(isset($_REQUEST['t']))
{
$td = $_REQUEST['t'];
$t = split(",",$td);
$all = "";
$box_in_row = 0 ;
$this_box="<table border=0><tr>";
foreach($t as $table)
{
$this_box = "<td><h3>$table</h3>";
$result = mysql_query("SHOW FULL COLUMNS FROM $table FROM prfxcom1_prfx");
$options = "";
while($r = mysql_fetch_object($result))
{
if(!empty($r->Comment))
{
$options .= "<br><input type=checkbox name=\"".$table."[]\" value='$r->Field' id=\"$table\">" . $r->Field;
}
}
if($table == "transfer_req")
{
$options .= "<br><input type=checkbox name=\"".$table."[]\" value='Net Profit' id=\"$table\">NetProfit";
}
$this_box .= $options;
// Button
$click = "$('#$table').attr('checked', 'checked')";
$button = "<br /><input style='margin-top:10px;' type='button' name='$table_button' id='$table_button' value=' Select All ' onclick=\"$click\"/>";
$all .= "<div class='tblBox'>".$this_box.$button."</div></td>";
}
//$all = "<table class=\"listing form\" cellpadding=\"0\" cellspacing=\"0\">".$all."</table>";
echo $all;
}
?>
Issue is faced in the line:
$click = "$('#$table').attr('checked', 'checked')";
Please suggest, I am stuck on this.
Thanks,
Hardik
WHAT???
$click = "$('#$table').attr('checked', 'checked')";
How can you write Javascript in the middle of a PHP file? It needs to be in script tags but even then PHP runs at the server and will not render your Javascript for you.
Add script tags, change your ID's to separate ones and give them the same class like tableClassName, and then write the following.
$(function(){
$('.tableClassName').attr('checked', 'checked')";
});
Ignoring the many issues with the code and simply answering the question:
You need to refer to the checkboxes using a class name not a ID (you have given them all the same ID)
For these lines: $options .= "<br><input type=checkbox name=\"".$table."[]\" value='$r->Field' id=\"$table\">" . $r->Field;
Change to: $options .= "<br><input type=checkbox name='" . $table . "[]' value='" . $r->Field ."' class='" . $table . "'>" . $r->Field;
For this line: $click = "$('#$table').attr('checked', 'checked')"; use single quotes or escape the $
Change to: $click = '$("."'.$table.'").attr("checked", "checked")';
I have created a CheckModulePermission function in my user class which checks a module table to ensure the user has permissions to view the page. Below is the function
public function CheckModulePermissions($moduleId) {
if(isset($_SESSION['userId'])) {
// If the user is admin, allow regardless
if($this->IsAdmin()) {
return true;
}
$sql = "SELECT `userModuleId`
FROM `userModules`
WHERE `userId` = " . $_SESSION['userId'] . "
AND `moduleId` = " . $moduleId . ";";
mysql_select_db(DB_USER_DATABASE_NAME, $this->conn);
$result = mysql_query($sql, $this->conn);
$x = mysql_fetch_row($result);
if($x[0] == 1) {
return true;
} else {
return false;
}
} else {
return false;
}
}
}
This works fine in all my pages except one page where it fails . I have a dropdown box and a text box which will be updated depending on the users permission. The user i am logged on as has the permission but the dropdown boxes do not appear.
if(isset($_GET['orderNumber'])) {
// If post is set then update the prima reference and order status
// Only if user has sufficient privileges
if(isset($_POST['orderStatus'])) {
if($user->CheckModulePermissions(11)) {
$cid->UpdateOrderStatus($_GET['orderNumber'], $_POST['orderStatus']);
$cid->UpdateOrderReference($_GET['orderNumber'], $_POST['PReference']);
}
}
if($user->CheckModulePermissions(11)) {
$content .= "<select name='orderStatus'>
<option value='1'";
if($orderDetails['status'] == 1) $content .= " selected='selected'";
$content .= ">Incomplete</option>
<option value='2'";
if($orderDetails['status'] == 2) $content .= " selected='selected'";
$content .= ">Submitted</option>
<option value='3'";
if($orderDetails['status'] == 3) $content .= " selected='selected'";
$content .= ">Processed</option>
</select>";
} else {
if($orderDetails['status'] == 1) $content .= "Incomplete";
if($orderDetails['status'] == 2) $content .= "Submitted";
if($orderDetails['status'] == 3) $content .= "Processed";
}
$content .= "</td>
</tr>
<tr>
<th>Prima Order Number</th>
<td>";
if($user->CheckModulePermissions(11)) {
$content .= "<input type='text' name='pReference' value='" . $orderDetails['PReference'] . "' /></td>
</tr>
<tr>
<td colspan='2'><input type='submit' /></td>
</tr>";
} else {
$content .= $orderDetails['PrimaReference'] . "</td></tr>";
}
$content .= "</table>
</form>
</td>
Is it the logic for the dropdown box where it fails?
Here is a more efficient/readable version of your CheckModulePermissions() method...
public function CheckModulePermissions ($moduleId) {
// Deny immmediately if no userId is set
if (!isset($_SESSION['userId'])) return FALSE;
// If the user is admin, allow regardless
if ($this->IsAdmin()) return TRUE;
// Generate an SQL statement - does this need sanitising?
$sql = "SELECT `userModuleId`
FROM `userModules`
WHERE `userId` = '{$_SESSION['userId']}'
AND `moduleId` = '$moduleId'
LIMIT 1";
// Is this line really necessary? Are you actually working with more than one database?
// Even if you are, it's probably better to do it in the query, like this:
// SELECT whatever FROM DB_USER_DATABASE_NAME.tablename WHERE...
mysql_select_db(DB_USER_DATABASE_NAME, $this->conn);
// Since you only want one row, it's slightly more resource efficient
// to abandon the $result variable
$x = mysql_fetch_row(mysql_query($sql, $this->conn));
// This means the same thing as your if ... else
return $x[0] == 1;
}
...and here is a rewritten version of the HTML generation code.
// Get this once, at the beginning, to minimise SQL traffic
$hasPermissions = $user->CheckModulePermissions(11);
// Uncomment this line to make sure that $user->CheckModulePermissions is returning the value you expect
//var_dump($hasPermissions);
if (isset($_GET['orderNumber'])) {
// If post is set then update the prima reference and order status
// Only if user has sufficient privileges
if (isset($_POST['orderStatus']) && $hasPermissions) {
$cid->UpdateOrderStatus($_GET['orderNumber'], $_POST['orderStatus']);
$cid->UpdateOrderReference($_GET['orderNumber'], $_POST['PReference']);
}
// Map of status numbers to string descriptions
$statusStrs = array(1 => 'Incomplete','Submitted','Processed');
if ($hasPermissions) {
// Generate a <select>
$content .= "<select name='orderStatus'>";
foreach ($statusStrs as $val => $str) {
$content .= "\n<option value='$val'".(($orderDetails['status'] == $val) ? " selected='selected'" : '').">$str</option>";
}
$content .= "\n</select>";
} else {
// Print the current status string
$content .= $statusStrs[$orderDetails['status']];
}
// Close the table cell (layout tables are nasty nasty)
$content .= "</td>
</tr>
<tr>
<th>Prima Order Number</th>
<td>";
if ($hasPermissions) {
// add an input for changing the reference number
$content .= "<input type='text' name='pReference' value='{$orderDetails['PReference']}' /></td>
</tr>
<tr>
<td colspan='2'><input type='submit' /></td>
</tr>";
} else {
// Display the current reference number
$content .= $orderDetails['PrimaReference'] . "</td></tr>";
}
$content .= "</table>
</form>
</td>
I think the most likely cause of your problem is that CheckModulePermissions() is returning FALSE when you expect it to return TRUE. Uncomment the var_dump() line to verify this and we'll take it from there.
Does anyone know how to display MySQL db hierarchical data (Nested Set Model (http://www.phpro.org/tutorials/Managing-Hierarchical-Data-with-PHP-and-MySQL.html)) in a combo box as shown here under the "Category:" comboxbox field:http://dir.globetourism.biz/submit.php
Thanks
What you need to do is when you print your <option> tags for your combo box you have to check the depth (how to get the depth is in the article that's linked in your question) of each element and print that many "| " strings and another two underscores (__) to give it a nice tree-like look.
<?PHP
function GetCats($id='0',$sublev='0',$vname='C_Parent')
{
$DQ = new MySQLTable;
$DQ -> TblName = 'cat_categories';
$WHERE[$vname]['=']=$id;
$res = $DQ -> Select('C_ID,C_Name',$WHERE,'C_ID');
if (mysql_num_rows($res)>0)
{
while($row = mysql_fetch_assoc($res))
{
$ss='';
if($sublev!=='0')
{
for($i=0;$i<=$sublev*10;$i++)
{
$ss.=' ';
}
$ss.='|';
for($i=0;$i<=$sublev;$i++)
{
$ss.='-';
}
$ss.='>>';
}
$sel_s = '';
if(IsSet($_POST['C_Parent']))
{
if($row['C_ID']==$_POST['C_Parent'])
{
$sel_s = ' selected';
}
} elseif (IsSet($_POST['I_Parent'])) {
if($row['C_ID']==$_POST['I_Parent'])
{
$sel_s = ' selected';
}
} else {
$sel_s = '';
}
Echo "<option value=\"".$row['C_ID']."\" ".$sel_s.">".$ss.$row['C_Name']."</option>\r\n";
GetCats($row['C_ID'],$sublev+1);
}
}
}
Echo "<select name=\"C_Parent\">\r\n";
Echo "<option value=\"0\">...</option>\r\n";
GetCats();
Echo "</select>";
?>
Something like this.
But here was my own MySQL class. The query is: SELECT C_ID,C_Name WHERE C_Parent=$id ORDER BY C_ID where $id - php variable (current parent cat).
And there are $_POST variables if error submit to store selected.
This is not the most effective way to di it bcoz many queries. More effectively is to get all data to array to work with.
I'm using a form where the user can edit an entry. Everything is populating and all is well with the exception that I can't get the drop down to show the project that they've already assigned the image to.
$project_qry = "SELECT * from projects ORDER BY title ASC";
$project_res = mysql_query($project_qry);
$project_drop = "<select name=\"project_id\">\n";
while ($row = mysql_fetch_array($project_res))
{
if ($project_id == $row[title])
{
$project_drop .= "<option value=\"$row[id]\" selected>$row[title]</option>\n";
}
else
{
$project_drop .= "<option value=\"$row[id]\">$row[title]</option>\n";
}
}
$project_drop .= "</select>\n";
I'm sure it's something devilishly simple but I'm stumped.
{
if ($project_id == $row[id])
{
$project_drop .= "<option value=\"$row[id]\" selected=\"selected\">$row[title]</option>\n";
}
else
{
$project_drop .= "<option value=\"$row[id]\">$row[title]</option>\n";
}
}
You need to compare the value and not the title. It is the value that gets posted ($_POST)
selected="selected" makes it XHTML compliant.
bigstylee answered correctly. I also recommend to separate the values of the array and your string:
$project_drop .= "<option value='". $row['id'] ."'>".$row['title']."</option>";
Also drop \n. Outputting \n won't generate a line break in the browser. And it is unnecessary.