Skip to content

Instantly share code, notes, and snippets.

@speedmax
Created March 31, 2009 02:47
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save speedmax/88016 to your computer and use it in GitHub Desktop.
Save speedmax/88016 to your computer and use it in GitHub Desktop.
concept for better active_record in CakePHP
<?php
class Person extends Model {
var $hasMany = 'hobbies';
}
class Hobby extends Model {
var $belongsTo = 'person';
}
echo Person::create(array(
'name' => 'taylor luk';
'hobbies_attributes' => array(
array('title'=>'swimming'),
array('title'=>'watch tv'),
)
))
# <Person id:1, "taylor luk">
echo Person::find(1)->name;
# "taylor luk"
echo Person::find(1)->hobbies->first;
# <Hobby id:1, "swimming">
?>
<?php
/*
Backward compat version of get_called_class
*/
if (!function_exists('get_called_class')):
function get_called_class() {
$bt = debug_backtrace();
$lines = file($bt[1]['file']);
preg_match('/([a-zA-Z0-9\_]+)::'.$bt[1]['function'].'/', $lines[$bt[1]['line']-1], $matches);
return $matches[1];
}
endif;
function set_static($class, $var) {
return eval('return ' . $class. '::$'. $var . ' = $value;');
}
function get_static($class, $var) {
return eval('return ' . $class. '::$'. $var . ';');
}
function call_static($callback) {
$args = func_get_args();
array_shift($args);
if (strpos('::', $callback) !== false)
$callback = explode('::', $callback);
return user_call_func_array($callback, $args);
}
class Model {
static $table;
static $inherited = array();
static $inheritColumn;
protected $associations;
protected $attributes;
/*
Class methods for table wide operation
*/
static create($attributes) {
$class = get_called_class();
$parents = class_parents($class);
$db =& Connection::dataSource('default');
$db->save('insert into '.get_static($class, 'table'). ' values (' . $db->toSql($attributes) . ')');
$instance = new $class($attributes);
$instance->id = $db->getLastInsertId();
return $instance;
}
static find($type, $conditions = array()) {
$class = get_called_class();
$db =& Connection::dataSource('default');
$rs = $db->query('select * from '. get_static($class, 'table') . ';');
return new ResultCollection($rs, $class);
}
static updateAll() {}
static deleteAll() {}
/*
instance methods for row wide operations
*/
# anyone suggestions about instance method of find?
# function find() {}
function delete() { }
function update() { }
function save() { }
# Magic
function __construct($attributes = array(), $ds = null) {
$class = get_called_class();
set_static($class, 'table', pluralize($class));
if (!empty($attributes))
return call_static("{$class}::create", $attributes);
}
function __get($attr) {
if (isset($this->attributes[$attr]))
return $this->attributes[$attr];
if (isset($this->associations[$attr]))
return $this->__fetchAssociation($attr);
}
function __set() {}
function __call() {}
function __toString() {}
function __find() { }
function __fetchAssociation() {
extract($this->associations[$attr]); // Extrac $className, $foreignKey, $conditions
$foreignKey = strtolower(__CLASS__)'_id';
$rs = call_static("{$className}::find", array(
'conditions'=> array($foreignKey = $this->id)
));
return new ResultCollection($rs, $className);
}
}
class ResultCollection extends ArrayObject {
function __construct($rs, $class) {
parent::__construct($rs);
foreach ($this as & $attributes) {
$item = new $class($attributes);
}
}
}
?>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment