Automatically Save PHP Class To Database | PHP | Object Mapping

Here is a class that you can use to save your models to the database every time they are changed. This allows the state of your object to persist.  This will make sure that your model (class or object) is being stored and it will be mapped to the database or retrieved from the database based on its ID.  

Here is how it works:

You create a model (see Dining_Room_Model) and a mapping class (see Dining_Room_DB_Mapper). You give the mapping class the data it needs to identify the object and where to store it in the database.



class Dining_Room_DB_Mapper extends DB_Property_Object {
 
 function __construct($init_id = 0) {
  $this->model = new Dining_Room_Model();
  $this->id = $init_id;
  $this->db_table_name = 'dinning_room';
  $this->db_key = 'object';
  $this->populate();
 }
 
 
 
}

You tell the mapping class where the model is that you want to store (see above: $this->model = new Dining_Room_Model();). Then this mapping class inherits from a class (DB_Property_Object) that detects any changes in the model and automatically saves a new seriallized version of the model to the database. The model can be retrieved from the database by ID or it creates a new entry if the ID does not already exist. Be aware of too many database accesses as this code could create a bottle next to your database. I would suggest reworking the code to only save on a save command being issued so that it saves all changes instead of saving it every time one of the properties are accessed.

Check out the code below for the full and complete example:

 

 
<?php 
/**
 * Dining Room Model and Datastore layer
 * @author nicholasdunbar
 *
 */
define('DB_NAME','test');
define('DB_USER', 'root');
define('DB_PASS', '');
//Requires PHP 5.3.0 or greater
if (!defined('PHP_VERSION_ID')) {
 $version = explode('.', PHP_VERSION);
 define('PHP_VERSION_ID', ($version[0] * 10000 + $version[1] * 100 + $version[2]));
}
//Check Version Number
if (PHP_VERSION_ID < 50300){
 exit();
}
/**
 * This class detects when a model changes and automatically backs it up to the database
 * @author nicholasdunbar
 *
 */
abstract class DB_Property_Object
{
 //Database link - it is static so that all DB_Property_Objects have access to it and it only has to be instantiated once.
 private static $database;
 //What ever model you want to save to the database, the model should be a flat class
 protected $model;
 //The name of the table where you intend to save the model
 protected $db_table_name;
 //the name of the field where you intend to save the model, it should be a binnary blob and each record should have an auto incementing id called 'id'
 protected $db_key;
 //the id of the saved model
 protected $id;
 
 
 public function __get($name)
 {
 if (isset($this->model) && property_exists($this->model, $name))
 {
 return $this->model->$name;
 } else {
 echo 'Cannot get: Does not contain property '.$name;
 }
 return NULL;
 }
 /**
  * Make sure that when any private accessors are changed that 
  * the object is backed up to the database
  * @param string $name
  * @param string $value
  */
 public function __set($name, $value)
 {
 $isChanged = FALSE;
 $serializedObj = NULL;
 $this->connect();
 if (isset($this->model) && property_exists($this->model, $name))
 {
 $isChanged = serialize($this->model->$name) != serialize($value);
 $this->model->$name = $value;
 if ($isChanged){
 $this->save();
 //save serialized object to the DB
 }
 //set data store
 } else {
 echo 'Cannot set: Does not contain property '.$name;
 }
 }
 public function get_id() {
 return $this->id;
 }
 /**
  * Populate the model from the database
  * @param int $id
  */
 protected function populate() {
 
 $testClass = NULL;
 $this->connect();
 
 if ($this->id == 0){
 $this->save();
 return;
 }
 
 //get the serialized object from the database
 $query = sprintf("SELECT %s FROM %s WHERE id=%d LIMIT 1", $this->db_key, $this->db_table_name, (int)($this->id));
 $result = mysql_query($query);
 $this->check_result($result, $query);
 
 // Populate model with result
 $row = mysql_fetch_assoc($result);
 $testClass = unserialize($row[$this->db_key]);
 try {
 $this->model = $testClass;
 } catch (Exception $e) {
 print_r($e);
 $message  = " \nInvalid object retrieved from the database";
 die($message);
 } 
 }
 
 /**
  * Saves a serialized version of the object to the database
  */
 private function save(){
 $this->connect();
 if ($this->id == 0){
 //there is no previously existing model
 //create an entry
 $query = sprintf("INSERT INTO ".$this->db_table_name." (".$this->db_key.") VALUES ('%s')",mysql_real_escape_string($this->serialize()));
 $result = mysql_query($query);
 $this->check_result($result, $query);
 } else {
 $serializedObj = $this->serialize();
 //save the serialized object to the DB
 $query = sprintf("UPDATE %s SET %s = '%s' WHERE id=%d", $this->db_table_name, $this->db_key, mysql_real_escape_string($serializedObj), $this->id);
 $result = mysql_query($query);
 $this->check_result($result, $query);
 }
 }
 
 private function check_result($result, $query){
 // Check result
 // This shows the actual query sent to MySQL, and the error.
 if (!$result) {
 $message  = 'Invalid query: ' . mysql_error() . "\n";
 $message .= 'Whole query: ' . $query;
 die($message);
 }
 }
 /**
  * Ensures that the object is connected to the database
  */
 private function connect(){
 //check to make sure these are defined 
 if (!isset($this->db_table_name)){
 die ('$db_table_name not defined');
 }
 if (!isset($this->db_key)){
 die ('$db_key not defined');
 }
 if (!isset($this->model)){
 die ('$model not defined');
 }
 if (!self::$database){
 self::$database = mysql_connect('localhost', DB_USER, DB_PASS);
 if (!self::$database) {
 die('Could not connect: ' . mysql_error());
 }
 $db_selected = mysql_select_db(DB_NAME, self::$database);
 if (!$db_selected) {
 die ('Can\'t use ' . DB_NAME . ' : ' . mysql_error());
 }
 }
 }
 
 /**
 * Serializes the entire object as a string for storage in the database
 * @return string
 */
 protected function serialize(){
 return serialize($this->model);
 }
 
}
/**
 * Model storing all data related to the dinning room
 * @author nicholasdunbar
 *
 */
class Dining_Room_Model{
 //number of tables in the restaurant
 public $tables = array();
 //number of waiters on the floor
 public $server_num = 0;
 //max amount of people that the floor can hold
 public $max_capacity_num = 0;
 //current number of customers in the dining room
 public $current_capacity_num = 0;
}
/**
 * Each time a property is changed this class will make sure the model is backed up to the database
 * @author nicholasdunbar
 *
 */
class Dining_Room_DB_Mapper extends DB_Property_Object {
 
 function __construct($init_id = 0) {
 $this->model = new Dining_Room_Model();
 $this->id = $init_id;
 $this->db_table_name = 'dinning_room';
 $this->db_key = 'object';
 $this->populate();
 }
 
 
 
}
//Chose the dinning room id. If the id is 0 then it 
//will create an id and you can retreive it with $dining_room->get_id();
$db_id = 1;
$dining_room = new Dining_Room_DB_Mapper($db_id);
//$dining_room->server_num = 20;
//$dining_room->max_capacity_num = 300;
//$dining_room->current_capacity_num = 120;
//$tables = $dining_room->tables;
//$tables[] = array("George","Paul","Linda");
//$tables[] = array("Josh","Suzy","Bob","Erin");
//$dining_room->tables = $tables;
echo $dining_room->server_num."\n";
echo $dining_room->max_capacity_num."\n";
print_r($dining_room->tables);
?>

 

Trackback(0)
Comments (0)add comment

Write comment
quote
bold
italicize
underline
strike
url
image
quote
quote
smile
wink
laugh
grin
angry
sad
shocked
cool
tongue
kiss
cry
smaller | bigger

security image
Write the displayed characters


busy