Part of the EllisLab Network
x
 
Create New Page
 View Previous Changes    ( Last updated by Beanlover )

Generate a form from a DB table

As is, this depends on XAJAX CI library.  If you just want to produce forms based on DB tables then use the “_formBuilder” function by itself by commenting-out/removing one line of code for it to be independent (there is a comment beside the line in the code below).

This code is released under the same license under which CI is released.

How to use this code:

1)Copy the functions below into your controller,
2)Create the tables described in the SQL towards the bottom of this page,
3)Create a view named “managetables” and paste the view code from the bottom of this page into it.
4)???
5)Profit!

Here are the functions required:

The _manageFields function is an internal function called using xajax:

/**
 * @author        Bob Beauchamp
 * @link        http://www.codeigniter.com/wiki/Generate_a_form_from_a_DB_table/
 */

function _manageFields($table){
  $table 
$this->input->xss_clean($table);
  
$fields $this->db->list_fields($table);
  foreach(
$fields as $field){
    $fieldQuery 
$this->db->getWhere('Management_fields',array('FieldName' => $field'InTable' => $table));
    if(
$fieldQuery->num_rows() > 0){
      $fieldRow 
$fieldQuery->result();
      
$fieldRow $fieldRow[0];
      if(
$fieldRow->AllowManagement){
        $displayFields[$field][$field] 
'<div id="'.$field.'manageToggle">'
                                        
.anchor('#','Make Unmanaged','onclick="xajax_toggleManagement(\''.$table.'\',\''.$field.'\');return false;"')
                                        .
'</div>';
      
}else{
        $displayFields[$field][$field] 
'<div id="'.$field.'manageToggle">'
                                        
.anchor('#','Make Managed','onclick="xajax_toggleManagement(\''.$table.'\',\''.$field.'\');return false;"')
                                        .
'</div>';
      
}
    }
  }
  $objResponse 
= new xajaxResponse();
  
$objResponse->addAssign($table."manageFields","innerHTML"ul($displayFields));
  return 
$objResponse->getXML();

The _addTabletoManagementTable function in an internal function called using xajax:

/**
 * @author        Bob Beauchamp
 * @link        http://www.codeigniter.com/wiki/Generate_a_form_from_a_DB_table/
 */

function _addTableToManagementTable($table){
  $table 
$this->input->xss_clean($table);
  
$tableQuery $this->db->getWhere('Management_tables',array('TableName' => $table));
  if(
$tableQuery->num_rows() == 0){
    $dbInsert 
= array('TableName'       => $table,
                      
'AllowManagement' => 1);
    
$this->db->insert('Management_tables',$dbInsert);
    
$fields $this->db->list_fields($table);
    foreach(
$fields as $field){
      $dbInsert 
= array('FieldName'       => $field,
                        
'InTable'         => $table,
                        
'AllowManagement' => 1);
      
$this->db->insert('Management_fields',$dbInsert);
    
}
  }
  $display 
anchor('#','Make Unmanaged','onclick="xajax_toggleManagement(\''.$table.'\');return false;"');
  
$objResponse = new xajaxResponse();
  
$objResponse->addAssign($table."manageToggle","innerHTML"$display);
  return 
$objResponse->getXML();

Simple xajax toggle for table management

/**
 * @author        Bob Beauchamp
 * @link        http://www.codeigniter.com/wiki/Generate_a_form_from_a_DB_table/
 */

function _toggleManagement($table,$field FALSE){
  $objResponse 
= new xajaxResponse();
  if(!
$field){
    $tableQuery 
$this->db->getWhere('Management_tables',array('TableName' => $table));
    if(
$tableQuery->num_rows() > 0){
      $tableRow 
$tableQuery->result();
      
$tableRow $tableRow[0];
      if(
$tableRow->AllowManagement){
        $this
->db->set('AllowManagement',0);
        
$display anchor('#','Make Managed','onclick="xajax_toggleManagement(\''.$table.'\');return false;"');
        
$objResponse->addAssign($table.'manageFields',"innerHTML"'');
      
}else{
        $this
->db->set('AllowManagement',1);
        
$display anchor('#','Make Unmanaged','onclick="xajax_toggleManagement(\''.$table.'\');return false;"');
        
$fieldDisplay anchor('#','Manage Fields','onclick="xajax_ManageFields(\''.$table.'\');return false;"');
        
$objResponse->addAssign($table.'manageFields',"innerHTML"$fieldDisplay);
      
}
      $this
->db->where('TableName',$table);
      
$this->db->update('Management_tables');
    
}
    $objResponse
->addAssign($table."manageToggle","innerHTML"$display);
  
}else{
    $fieldQuery 
$this->db->getWhere('Management_fields',array('FieldName' => $field'InTable' => $table));
    if(
$fieldQuery->num_rows() > 0){
      $fieldRow 
$fieldQuery->result();
      
$fieldRow $fieldRow[0];
      if(
$fieldRow->AllowManagement){
        $this
->db->set('AllowManagement',0);
        
$display anchor('#','Make Managed','onclick="xajax_toggleManagement(\''.$table.'\',\''.$field.'\');return false;"');
      
}else{
        $this
->db->set('AllowManagement',1);
        
$display anchor('#','Make Unmanaged','onclick="xajax_toggleManagement(\''.$table.'\',\''.$field.'\');return false;"');
      
}
      $this
->db->where('FieldName',$field);
      
$this->db->where('InTable',$table);
      
$this->db->update('Management_fields');
    
}
    $objResponse 
= new xajaxResponse();
    
$objResponse->addAssign($field."manageToggle","innerHTML"$display);
  
}
  
return $objResponse->getXML();

This is the function you want to reference from your browser in order to start the magic rolling.

/**
 * @author        Bob Beauchamp
 * @link        http://www.codeigniter.com/wiki/Generate_a_form_from_a_DB_table/
 */

function managetables(){
  $this
->load->library('xajax');
  
$this->xajax->registerFunction(array('toggleManagement',&$this,'_toggleManagement'));
  
$this->xajax->registerFunction(array('addTableToManagementTable',&$this,'_addTableToManagementTable'));
  
$this->xajax->registerFunction(array('ManageFields',&$this,'_ManageFields'));
  
$this->xajax->processRequests();

  
$tables $this->db->list_tables();
  foreach(
$tables as $table){
    
if($table != 'Management_tables' && $table != 'Management_fields'){
      $tableQuery 
$this->db->getWhere('Management_tables',array('TableName' => $table));
      if(
$tableQuery->num_rows() > 0){
        $tableRow 
$tableQuery->result();
        
$tableRow $tableRow[0];
        if(
$tableRow->AllowManagement){
          $displayTables[$table][$table] 
'<div id="'.$table.'manageToggle">'
                                          
.anchor('#','Make Unmanaged','onclick="xajax_toggleManagement(\''.$table.'\');return false;"')
                                          .
'</div>'
                                          
.'<div id="'.$table.'manageFields">'
                                          
.anchor('#','Manage Fields','onclick="xajax_ManageFields(\''.$table.'\');return false;"')
                                          .
'</div>';
        
}else{
          $displayTables[$table][$table] 
'<div id="'.$table.'manageToggle">'
                                          
.anchor('#','Make Managed','onclick="xajax_toggleManagement(\''.$table.'\');return false;"')
                                          .
'</div>'
                                          
.'<div id="'.$table.'manageFields">'
                                          
.'</div>';
        
}
      }else{
        $displayTables[$table][$table] 
'<span id="'.$table.'manageToggle">'
                                         
.anchor('#','Add to Management_tables table','onclick="xajax_addTableToManagementTable(\''.$table.'\');return false;"')
                                         .
'</span>';
      
}
    }
  }
  $data[
'xajax_js'$this->xajax->getjavascript(null'/_js/xajax.js');
  
$data['content'ul($displayTables);
  
$this->load->view('managetables',$data);

I have made this an internal function so I can just call it from other functions and have it return the basic form elements.  Can work as a url-addressable function with some minor tweaks.  This function depends on the table being passed into to already being in the management tables (see SQL code below).  I have debated making it automatically suck the table and fields into the management tables but have not yet taken that step since I like to be a bit more hands-on with this kind of thing.

/**
 * @author        Bob Beauchamp
 * @link        http://www.codeigniter.com/wiki/Generate_a_form_from_a_DB_table/
 */

function _formBuilder($table,$values=array(),$valuesAsHidden=FALSE){
  $columns 
$this->db->query($this->db->_list_columns($table));
  if(
$columns->num_rows() > 0){
    
foreach ($columns->result_array() as $columnInfo){
      
foreach($columnInfo as $key => $val){
        
if($key == 'Field'){
          $fieldName 
$val;
          if(!
$this->data->getManagementStatus($table,$fieldName)) break;  //comment this out if you are using only this function and not the supporting "management" fuctions
        
}
        $arrTableInfo[$fieldName][$key] 
$val;
      
}
    }
    $formDisplay 
'';
    foreach(
$arrTableInfo as $fieldName => $arrInfo){
      $arrFormField 
'';
      if(isset(
$values[$fieldName])){
        $arrFormField[$fieldName] 
$values[$fieldName];
        
$formFunction 'form_hidden';
      
}else{
        
if($fieldName == 'InCity' && $table == 'minisites'){
          $selectName 
$fieldName;
          
$selectExtra ' class="cms_form_dropdown"';
          
$retval[$fieldName] form_dropdown($selectName,$this->data->getCityArray(),'',$selectExtra);
          continue;
        
}
        $arrFormField[
'name'$fieldName;
        
$arrFormField['id']   $fieldName;
        foreach(
$arrInfo as $key => $val){
          
switch($key){
           
case 'Type':
             
$formType explode('(',$val);
             switch(
$formType[0]){
              
case 'varchar'//always has a size
              
case "char":
                
$formFunction 'form_input';
                
$arrFormField['maxlength'str_replace(')','',$formType[1]);
                break;
              case 
"tinyint":
              case 
"smallint":
              case 
"mediumint":
              case 
"int":
              case 
"bigint":
                
$formFunction 'form_input';
                
$numericInfo explode(' ',$formType[1]);
                
$arrFormField['maxlength'str_replace(')','',$numericInfo[0]);
                if(isset(
$numericInfo[1])){
                  $validationExtras 
$numericInfo[1];
                
}
                
break;
              case 
"datetime":
              case 
"timestamp":
                
$formFunction 'form_input';
                
$arrFormField['maxlength''19';
                break;
              case 
"float":
                
$formFunction 'form_input';
                
$arrFormField['maxlength''23';
                break;
              case 
"double":
                
$formFunction 'form_input';
                
$arrFormField['maxlength''53';
                break;
              case 
"decimal":
                
$formFunction 'form_input';
                
$arrFormField['maxlength''64';
                break;
              case 
"date":
                
$formFunction 'form_input';
                
$arrFormField['maxlength''10';
                break;
              case 
"year":
                
$formFunction 'form_input';
                
$arrFormField['maxlength''4';
                break;
              case 
"time":
                
$formFunction 'form_input';
                
$arrFormField['maxlength''8';
                break;
              case 
'tinytext':
                
$formFunction 'form_input';
                if(isset(
$formType[1])){
                  $arrFormField[
'maxlength'str_replace(')','',$formType[1]);
                
}else{
                  $arrFormField[
'maxlength''255';
                
}
                
break;
              case 
'text':
                
$formFunction 'form_textarea';
                if(isset(
$formType[1])){
                  $arrFormField[
'maxlength'str_replace(')','',$formType[1]);
                
}else{
                  $arrFormField[
'maxlength''65535';
                
}
                
break;
              case 
'mediumtext':
              case 
'longtext':
                
$formFunction 'form_textarea';
                if(isset(
$formType[1])){
                  $arrFormField[
'maxlength'str_replace(')','',$formType[1]);
                
}else{
                  $arrFormField[
'maxlength''16777215';
                
}
                
break;
              case 
'set':
                
$formFunction 'form_dropdown';
                
$selectExtra 'multiple="multiple"';
                
$setVals explode(',',$val);
                
$totalVals count($setVals);
                
$setVals[0] str_replace("set('",'',$setVals[0]);
                
$setVals[($totalVals 1)str_replace("')",'',$setVals[($totalVals 1)]);
                foreach(
$setVals as $key => $val){
                  $setVals[$key] 
str_replace("'",'',$setVals[$key]);
                  
$arrFormField[$setVals[$key]] $setVals[$key];
                
}
                
break;
              case 
'enum':
                
$formFunction 'form_dropdown';
                
$selectExtra '';
                
$enumVals explode(',',$val);
                
$totalVals count($enumVals);
                
$enumVals[0] str_replace("enum('",'',$enumVals[0]);
                
$enumVals[($totalVals 1)str_replace("')",'',$enumVals[($totalVals 1)]);
                
$arrFormField['selectone''Select One';
                foreach(
$enumVals as $key => $val){
                  $enumVals[$key] 
str_replace("'",'',$enumVals[$key]);
                  
$arrFormField[$enumVals[$key]] $enumVals[$key];
                
}
                
break;
             
}
             
break;
           case 
'Null':
             
//todo: should there be a "required" validation rule based on this?
             //      currently I'm leaning towards "no" and making them specify
             //      validation rules separately and deliberately
             
break;
           case 
'Key':
             if(
$val != ''){
               
if(@$validationExtras != ''){
                 $validationExtras 
.= '|'.$val;
               
}else{
                 $validationExtras 
$val;
               
}
             }
             
break;
           case 
'Default':
             
//$arrFormField['value'] = $val; //considering leaving this out since the default is going
             //to be populated if there is no value.  Would have to unset
             //the value before inserting/updating the DB record
             
break;
           case 
'Extra':
             break;
          
}
        }
      }
      
if($formFunction != "form_dropdown"){
        
if($formFunction != 'form_hidden'){
          $arrFormField[
'class''css_'.$formFunction;
        
}
        $retval[$fieldName] 
$formFunction($arrFormField);
      
}else{
        $selectName 
$arrFormField['name'];
        unset(
$arrFormField['name']);
        unset(
$arrFormField['id']);
        
$selectExtra .= ' class="css_'.$formFunction.'"';
        
$retval[$fieldName] $formFunction($selectName,$arrFormField,'selectone',$selectExtra);
      
}
    }
  }else{
    $retval 
FALSE;
  
}
  
return $retval;

Here is the SQL (exported from mySQL) to create the management tables:

-- 
-- 
Table structure for table `Management_fields`
-- 

CREATE TABLE `Management_fields` (
  `
FieldNamevarchar(255NOT NULL,
  `
InTablevarchar(255NOT NULL,
  `
AllowManagementtinyint(1NOT NULL default '1',
  
PRIMARY KEY  (`FieldName`,`InTable`)
TYPE=MyISAM;

-- --------------------------------------------------------

-- 
-- 
Table structure for table `Management_tables`
-- 

CREATE TABLE `Management_tables` (
  `
TableNamevarchar(255NOT NULL,
  `
AllowManagementtinyint(1NOT NULL default '1',
  
PRIMARY KEY  (`TableName`)
TYPE=MyISAM

My simple view for the “managetables” function:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<
html xmlns="http://www.w3.org/1999/xhtml">
<
head>
<?=$xajax_js;?>
</head>
<
body>
<?=$content;?>
</body>
</
html