[eluser]wiredesignz[/eluser]
Contributions in this thread are based on AutoModel by Developer13 and modified with permission.
Quote:Code is removed from this post, please look at the updates below
[eluser]wiredesignz[/eluser]
An example table model
Quote:Code is removed from this post, please look at the updates below
[eluser]Developer13[/eluser]
Hey, that looks vaguely familiar... now where have I seen this before...
[eluser]Sam Dark[/eluser]
Another one based on Developer13's AutoModel:
Code: <?php
/**
* AutoModel PHP5
* @version 0.1
* @author Initial idea and code by Developer13 (http://ellislab.com/forums/member/41286/)
* @author Sam Dark
*/
class AutoModel extends Model {
public $return_method = 'object';
protected $table = null;
//id is most commonly used for primary key
protected $primary_key = 'id';
//if array - define alias
//if no . in name - use current table name
protected $fields = array();
/**
* Behaviors could automate your models even more. Currently there is only one supported.
* TimestampableBehavior. Updates created_on and updated_on in model table with
* current unix timestamp.
*
* Usage:
* $this->addBehavior(new TimestampableBehavior());
*/
private $behaviors = array();
/**
* $joins = array(
* 'table_name1' => 'table_name1.id = id',
* 'table_name2' => array('table_name2.id = id', 'left'),
* )
*
* @see $this->db->join(); in Active Record section in user guide for join types
*/
protected $joins = array();
function __construct() {
parent::__construct();
}
function addBehavior(AutomodelBehavior $behavior){
$this->behaviors[] = $behavior;
}
/**
* If there is no table name add this model table name.
*/
private function update_fields(){
foreach ($this->fields as &$field){
if(!stristr($field, '.')){
$field = $this->table.'.'.$field;
}
}
}
/**
* Get records from model.
*
* @param array|string $where
* @param int|array $limit
* @return array
*
* @see /database/active_record.html
* You can use methods 3 and 4 from User Guide on $this->db->where().
*
* For $limit you can use int to produce LIMIT n
* or array(limit, offset) to produce LIMIT limit, offset
*/
function get($where = null, $limit = null, $protect = true) {
$this->update_fields();
$this->db->select($this->fields);
if (!empty($where)){
$this->db->where($where, null, $protect);
}
$this->perform_join();
if(is_array($limit)){
$query = $this->db->get($this->table, $limit[0], $limit[1]);
}
else {
$query = $this->db->get($this->table, $limit);
}
if ($this->return_method == 'object') {
if ($limit == 1) {
return $query->row();
}
else {
return $query->result();
}
}
elseif ($this->return_method == 'array') {
if ($limit == 1) {
return $query->row_array();
}
else {
return $query->result_array();
}
}
}
/**
* Saves data to the model.
*
* @param array|string $where if specified, update query is generated, else insert query
* @see also $this->get description
* @param array $db_array
* //TODO: save data to joined models?
* You can specify data to save manually instead of getting it from POST. To do it use
* second parameter.
*/
function save($where = null, $data = null) {
if(empty($data)) $data = $this->db_array();
$this->db->set($data);
if (!empty($where)) {
if(!empty($this->behaviors)){
foreach ($this->behaviors as $behavior){
$behavior->on_update($this);
}
}
$this->db->where($where);
$this->db->update($this->table);
}
else {
if(!empty($this->behaviors)){
foreach ($this->behaviors as $behavior){
$behavior->on_insert($this);
}
}
$this->db->insert($this->table);
}
}
/**
* Deletes model record based on condition.
* //TODO: delete data from joined models?
*
* @param array|string $where
*/
function delete($where) {
if(!empty($this->behaviors)){
foreach ($this->behaviors as $behavior){
$behavior->on_delete($this);
}
}
$this->db->where($where);
$this->db->delete($this->table);
}
/**
* Adds joins to the query based on $this->join.
*/
private function perform_join() {
if (!empty($this->joins)) {
foreach ($this->joins as $table => $condition) {
if(is_array($condition)){
$this->db->join($table, $condition[0], $condition[1]);
}
else {
$this->db->join($table, $condition);
}
}
}
}
/**
* Fills array for save from POST.
* Form must have the same names as specified in the model definition.
*
* @return array
*/
private function db_array() {
$db_array = array();
foreach ($this->fields as $field) {
$field = substr($field, strpos($field, '.') + 1);
if (isset($_POST[$field])) {
$db_array[$field] = $this->input->post($field);
}
}
return ($db_array);
}
}
[eluser]Sam Dark[/eluser]
Code: abstract class AutomodelBehavior {
/**
* Enter description here...
*
* @param AutoModel $model
*/
function on_insert($model){}
/**
* Enter description here...
*
* @param AutoModel $model
*/
function on_update($model){}
/**
* Enter description here...
*
* @param AutoModel $model
*/
function on_delete($model){}
}
/**
* Automatically fills updated_on and created_on with current unix timestamps
* //TODO: timezones support
*/
class TimestampableBehavior extends AutomodelBehavior {
function on_insert($model){
$model->db->set($model->table.'.created_on', time());
}
function on_update($model){
$model->db->set($model->table.'.updated_on', time());
}
}
[eluser]Sam Dark[/eluser]
Sample model:
Code: <?php
class User extends AutoModel {
function __construct(){
parent::__construct();
$this->table = 'users';
$this->fields = array(
'login',
'password',
'email',
'created_on',
'updated_on'
);
$this->addBehavior(new TimestampableBehavior());
}
}
I think we need to combine our approaches to get maximum out of this.
[eluser]wiredesignz[/eluser]
Great contribution Sam, let me look at this and post back.
In the meantime take a look at this, I am now using this updated AutoModel class to replace the CI Model entirely.
Code: <?php if (!defined('BASEPATH')) exit('No direct script access allowed');
/**
* AutoModel PHP5
* Based on AutoModel by Developer13
* http://ellislab.com/forums/viewthread/88769/
*
* Install this file as application/libraries/Model.php
*
* @version: 0.7 (c) Wiredesignz 2008-08-22
*/
class Model
{
protected $table, $joins, $pk, $fields, $order_by;
protected $resultset;
public function __construct()
{
log_message('debug', get_class($this)." Model initialised");
$this->_assign_libraries();
}
public function get($pk = NULL)
{
/* set fields for select */
$this->db->select($this->fields[$this->table]);
$this->perform_joins();
/* set order by */
if (isset($this->order_by))
$this->db->order_by($this->order_by);
/* set primary key? */
if (is_numeric($pk))
$this->db->where($this->pk, $pk);
/* return the query resource */
return $this->db->get($this->table);
}
public function save($data)
{
$this->prep_dataset($data);
/* valid data and pk type? */
if (is_numeric($data[$this->pk]))
{
$this->db->where($this->pk, $data[$this->pk]);
/* do update */
if($this->db->update($this->table, $data))
return $data[$this->pk];
}
/* do insert */
elseif($this->db->insert($this->table, $data))
return $this->db->insert_id();
}
public function delete($pk = NULL)
{
/* valid pk type? */
if (is_numeric($pk))
{
$this->db->where($this->pk, $pk);
/* do delete */
return $this->db->delete($this->table);
}
}
private function perform_joins()
{
/* valid joins array? */
if (is_array($this->joins))
{
foreach (array_keys($this->joins) as $key)
{
/* build the join keys array */
$this->db->join($key, $key.'.'.$this->joins[$key]);
/* add the join fields to select */
$this->db->select($this->fields[$key]);
}
}
}
private function prep_dataset($data)
{
/* prepare the data */
foreach ($this->fields[$this->table] as $field)
{
/* match data keys to fields */
if (isset($data[$field]))
{
/* set the fields */
$this->db->set($field, $data[$field]);
}
}
}
public function _assign_libraries()
{
if ($db = controller::instance()->db) // Modular Extensions PHP5 - controller::instance()
{
(isset($this->db)) OR $this->db = $db;
}
}
}
[eluser]wiredesignz[/eluser]
Example table model
Code: <?php if (!defined('BASEPATH')) exit('No direct script access allowed');
/**
* Site Model
*
**/
class Site_model extends Model
{
public function __construct()
{
parent::__construct();
$this->table = 'site';
$this->pk = 'site_id';
$this->joins = array(
'language' => 'language_id = site.language_id',
'theme' => 'theme_id = site.theme_id',
);
/* site table fields */
$this->fields['site'] = array(
'site_id',
'site',
'title',
'description',
'n',
'enabled',
'protected',
'site.theme_id',
'site.language_id',
);
/* language table fields */
$this->fields['language'] = array(
'option',
'language',
);
/* theme table fields */
$this->fields['theme'] = array(
'source',
'theme',
'partial',
);
$this->order_by = "n";
}
public function sites()
{
return parent::get()->result();
}
public function site($site, $pk = NULL)
{
(is_numeric($site)) ? $pk = $site : $this->db->where('site.site', $site);
return parent::get($pk)->row();
}
}
[eluser]Developer13[/eluser]
BATTLE OF THE AUTOMODELS!!!
*insert dramatic music here*
[eluser]Thorpe Obazee[/eluser]
This has been posted a long while ago but I wonder if anyone did continue on building this?
|