PHP model for automatic SQL and form creation
Friday, January 16th, 2009After using Django and it’s hibernate-like Object-Relational Model (ORM) for a month or so, I decided to try how I could create a similar model mechanism using PHP. Here’s an example which I wanted to keep just under 100 lines for light reading. This example code demonstrates how to:
- Easily create a structure with various types of fields (though currently it only supports CharField)
- Generate SQL code for table creation
- Generate a HTML form for editing the information
When you run the example, it will output the following (note the intentional error in the SQL statement syntax):
CREATE TABLE `person` (
`id` integer AUTO_INCREMENT NOT NULL PRIMARY KEY,
`name` VARCHAR(40),
`address` VARCHAR(40),
`phone` VARCHAR(15),
);<form action=’.’ method=’POST’>
<table>
<tr><th>Name</th><td></td></tr>
<tr><th>Address</th><td></td></tr>
<tr><th>Phone</th><td></td></tr>
</table>
</form>
The code itself is here for you to use in any way you please, as long as you don’t hold me accountable for the results:
<?php
class Field
{
var $size;
var $label;
var $editor;
var $value;
function __construct($size = 80, $label = '')
{
$this->size = $size;
$this->label = $label;
}
}
class CharField extends Field
{
function __construct($size = 80, $label = '')
{
$this->editor = 'input type="text"';
parent::__construct($size, $label);
}
function get_db_type()
{
return 'VARCHAR('.$this->size.')';
}
}
class Model
{
function get_name()
{
return get_class($this);
}
function make_create_sql()
{
$str = '';
echo "nCREATE TABLE `",strtolower($this->get_name()),"` (n";
echo " `id` integer AUTO_INCREMENT NOT NULL PRIMARY KEY,n";
foreach ( get_class_vars($this->get_name()) as $x => $y)
{
echo ' `',$x,'` ',$this->$x->get_db_type(),",n";
}
echo ");nn";
}
function make_form()
{
foreach ( get_class_vars($this->get_name()) as $x => $y)
{
echo $this->$x->label,': <',$this->$x->editor,' name="',$x,"\">n";
}
}
function make_form_table()
{
echo " <table class=\"mytable\">n";
foreach ( get_class_vars($this->get_name()) as $x => $y)
{
echo ' <tr><th>',$this->$x->label,'</th><td><',
$this->$x->editor,' name="',$x,'" value="'.$this->$x->value.
"\"></td></tr>n";
}
echo " </table>n";
}
}
class Person extends Model
{
var $name, $address, $phone;
function __construct()
{
$this->name = new CharField(40, 'Name');
$this->address = new CharField(40, 'Address');
$this->phone = new CharField(15, 'Phone');
}
}
$j = new Person();
$j->name->value = "Erkki Tapola";
$j->make_create_sql();
echo "<form action='.' method='POST'>n";
$j->make_form_table();
echo "</form>n";
?>
You can easily add more field types according to the example CharField. Other features also available in Django, but this example doesn’t (yet) implement:
- Query mechanisms to abstract SQL SELECT.
- Persistence; save mechanisms to abstract UPDATE and INSERT.
- Database table relation, fetch rows based on foreign keys and many-to-many relations
In addition, what I would like to see in Django:
- Methods to update the current database schema with the added and modified field information. (Note: Check out Django-evolution, which is doing exactly this, and it even maintains a history of modifications.
Such a functionality would be safe for added columns and even column truncation and removal, as long as you indicate that this is actually your intent.