Write custom persistent models
This code depends on Pimcore build 1638 but should work fine on older releases, too.
When to use custom models
The pimcore objects are very flexible but shouldn't be use to store all types of data. For example it doesn't make sense to implement a rating-, comments- or a complex blog system on top of the pimcore objects. Sometimes people also implementing really interesting things just to get a unique object key or try to build n to n relationships. This produce really ugly code, could be very slow, is hard to refactor and you will have a lot of pain if you have to merge multiple installations.
Database
In this example i will show you how you can save a custom model in the database.
At first create the database structure for the model, for this example i'll use a very easy model called vote. it just has an id, an username (just a string) and a score. If you want to write a model for a Plugin you have to create the table(s) during the installation.
CREATE TABLE `votes` ( `id` int(11) NOT NULL AUTO_INCREMENT, `username` varchar(255) DEFAULT NULL, `score` int(5) DEFAULT NULL, PRIMARY KEY (`id`) ) ENGINE=MyISAM AUTO_INCREMENT=44 DEFAULT CHARSET=utf8
Please mind that this is just a generic example, you also could create other and more complex models.
Model
Now you have to implement the model. To make it easy the model is stored into the Website library. You also could locate it into a Plugin library. Just make sure that the autoloader can locate it.
# website/lib/Website/Model/Vote.php <?php class Website_Model_Vote extends Pimcore_Model_Abstract { public $id; public $username; public $score; public function save() { return $this->getResource()->save(); } public static function getById($id) { $obj = new self; $obj->getResource()->getById($id); return $obj; } // just getters/setters public function setScore($score) { $this->score = $score; } public function getScore() { return $this->score; } public function setUsername($username) { $this->username = $username; } public function getUsername() { return $this->username; } public function setId($id) { $this->id = $id; } public function getId() { return $this->id; } }
For every field in the database we need a corresponding property and a Setter/Getter. This is not really necessary, it just depends on your resource, just read on and have a look at the save method in the resource.
The save and getById methods just call the corresponding resource methods.
The getResouce method looks for the nearest resouce. It just appends _Resouce to the classname, if the class exists you are ready to use the resouce. if the class doesn't exists, it just continue searching using the next namespace.
Small example: Website_Model_Vote looks for Website_Model_Vote_Resouce, Website_Model_Resouce, Website_Resouce.
Resource
Now we are ready to implement the Resouce:
#website/lib/Website/Model/Resource.php <?php class Website_Model_Vote_Resource extends Pimcore_Model_Resource_Abstract { protected $tableName = 'votes'; public function getById($id = null) { if ($id != null) $this->model->setId($id); $data = $this->db->fetchRow('SELECT * FROM '.$this->tableName.' WHERE id = ?', $this->model->getId()); if(!$data["id"]) throw new Exception("Object with the ID " . $this->model->getId() . " doesn't exists"); $this->assignVariablesToModel($data); } public function save() { $vars = get_object_vars($this->model); $buffer = array(); $validColumns = $this->getValidTableColumns($this->tableName); if(count($vars)) foreach ($vars as $k => $v) { if(!in_array($k, $validColumns)) continue; $getter = "get" . ucfirst($k); if(!is_callable(array($this->model, $getter))) continue; $value = $this->model->$getter(); if(is_bool($value)) $value = (int)$value; $buffer[$k] = $value; } if($this->model->getId() !== null) { $this->db->update($this->tableName, $buffer); return; } $this->db->insert($this->tableName, $buffer); $this->model->setId($this->db->lastInsertId()); } public function delete() { $this->db->delete($this->tableName, $this->db->quoteInto("id = ?", $this->model->getId())); } }
Please mind that this is just a very easy example resource. You also could do more complex stuff like implementing joins, save dependencies or whatever you want.
Using the Model
Now you can use your Model in your Servicelayer.
$vote = new Website_Model_Vote();
$vote->setScore(3);
$vote->setUsername('foobar!'.mt_rand(1, 999));
$vote->save();
Testing the Model
soon ....