Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

Added has_one, has_many, and belongs_to relationships to Models via _…

…_call()
  • Loading branch information...
commit 8574c027f23082d3c70ebeba688cba52440f4af3 1 parent 22a721c
@jbroadway authored
Showing with 118 additions and 8 deletions.
  1. +52 −4 lib/Model.php
  2. +3 −3 tests/DBTest.php
  3. +63 −1 tests/ModelTest.php
View
56 lib/Model.php
@@ -201,16 +201,64 @@ public function __construct ($vals = false, $is_new = true) {
/**
* Custom caller to handle references to related models.
+ * Handles one-to-one and one-to-many relationships via
+ * dynamic methods based on the field names.
*/
public function __call($name, $arguments) {
- if (isset ($this->data[$name]) && isset ($this->fields[$name]) && isset ($this->fields[$name]['ref'])) {
- if (isset ($this->{'_ref_' . $name})) {
+ // method not found in dynamic fields
+ if (! isset ($this->fields[$name])) {
+ $trace = debug_backtrace ();
+ trigger_error (
+ sprintf ('Call to undefined method %s::%s in %s on line %d',
+ get_class ($this),
+ $name,
+ $trace[0]['file'],
+ $trace[0]['line']
+ ),
+ E_USER_ERROR
+ );
+ }
+
+ // if true is passed, re-fetch from the database
+ $reset_cache = (count ($arguments) > 0) ? $arguments[0] : false;
+
+ if (isset ($this->fields[$name]['ref'])) {
+ // for backwards compatibility
+ $this->fields[$name]['belongs_to'] = $this->fields[$name]['ref'];
+ unset ($this->fields[$name]['ref']);
+ }
+
+ if (isset ($this->fields[$name]['belongs_to'])) {
+ // handle belongs_to relationships (reverse of one to one or one to many)
+ if (! $reset_cache && isset ($this->{'_ref_' . $name})) {
return $this->{'_ref_' . $name};
}
- $class = $this->fields[$name]['ref'];
- $this->{'_ref_' . $name} = new $class ($this->data[$name]);
+ $class = $this->fields[$name]['belongs_to'];
+ $field_name = isset ($this->fields[$name]['field_name']) ? $this->fields[$name]['field_name'] : $name;
+ $this->{'_ref_' . $name} = new $class ($this->data[$field_name]);
+ return $this->{'_ref_' . $name};
+
+ } elseif (isset ($this->fields[$name]['has_one'])) {
+ // handle has_one relationships (one to one)
+ if (! $reset_cache && isset ($this->{'_ref_' . $name})) {
+ return $this->{'_ref_' . $name};
+ }
+ $class = $this->fields[$name]['has_one'];
+ $field_name = isset ($this->fields[$name]['field_name']) ? $this->fields[$name]['field_name'] : $this->table;
+ $this->{'_ref_' . $name} = $class::query ()->where ($field_name, $this->data[$this->key])->single ();
+ return $this->{'_ref_' . $name};
+
+ } elseif (isset ($this->fields[$name]['has_many'])) {
+ // handle has_many relationships (one to many)
+ if (! $reset_cache && isset ($this->{'_ref_' . $name})) {
+ return $this->{'_ref_' . $name};
+ }
+ $class = $this->fields[$name]['has_many'];
+ $field_name = isset ($this->fields[$name]['field_name']) ? $this->fields[$name]['field_name'] : $this->table;
+ $this->{'_ref_' . $name} = $class::query ()->where ($field_name, $this->data[$this->key])->fetch ();
return $this->{'_ref_' . $name};
}
+
$trace = debug_backtrace ();
trigger_error (
sprintf ('Call to undefined method %s::%s in %s on line %d',
View
6 tests/DBTest.php
@@ -88,9 +88,9 @@ function test_shift_array () {
function test_pairs () {
$cmp = new StdClass;
$cmp->foo = 'asdf';
- db_execute ('create table test2 (foo char(12), bar char(12))');
- db_execute ('insert into test2 (foo, bar) values (?, ?)', 'one', 'joe');
- db_execute ('insert into test2 (foo, bar) values (?, ?)', 'two', 'sam');
+ DB::execute ('create table test2 (foo char(12), bar char(12))');
+ DB::execute ('insert into test2 (foo, bar) values (?, ?)', 'one', 'joe');
+ DB::execute ('insert into test2 (foo, bar) values (?, ?)', 'two', 'sam');
$res = DB::pairs ('select * from test2 order by foo asc');
$cmp = array ('one' => 'joe', 'two' => 'sam');
$this->assertEquals ($res, $cmp);
View
64 tests/ModelTest.php
@@ -1,5 +1,6 @@
<?php
+require_once ('lib/Functions.php');
require_once ('lib/Autoloader.php');
class Qwerty extends Model {
@@ -7,18 +8,65 @@ class Qwerty extends Model {
}
class Foo extends Model {}
+
class Bar extends Model {
var $fields = array (
'foo' => array ('ref' => 'Foo')
);
}
+class Gallery extends Model {
+ public $fields = array (
+ 'cover' => array ('has_one' => 'Cover'),
+ 'items' => array ('has_many' => 'Item', 'field_name' => 'gallery_id')
+ );
+}
+
+class Cover extends Model {
+ public $fields = array (
+ 'gallery' => array ('belongs_to' => 'Gallery')
+ );
+}
+
+class Item extends Model {
+ public $fields = array (
+ 'gallery' => array ('belongs_to' => 'Gallery', 'field_name' => 'gallery_id')
+ );
+}
+
class ModelTest extends PHPUnit_Framework_TestCase {
protected static $q;
static function setUpBeforeClass () {
DB::open (array ('master' => true, 'driver' => 'sqlite', 'file' => ':memory:'));
- DB::execute ('create table qwerty ( foo char(12), bar char(12) )');
+ $sql = sql_split ("create table qwerty ( foo char(12), bar char(12) );
+ create table gallery (
+ id integer primary key,
+ title char(48)
+ );
+ create table cover (
+ id integer primary key,
+ gallery integer unique,
+ title char(48)
+ );
+ create table item (
+ id integer primary key,
+ gallery_id integer,
+ title char(48)
+ );
+ insert into gallery (id, title) values (1, 'Gallery One');
+ insert into cover (id, gallery, title) values (1, 1, 'Cover One');
+ insert into item (id, gallery_id, title) values (1, 1, 'Item One');
+ insert into item (id, gallery_id, title) values (2, 1, 'Item Two');
+ insert into item (id, gallery_id, title) values (3, 1, 'Item Three');
+ insert into gallery (id, title) values (2, 'Gallery Two');
+ insert into cover (id, gallery, title) values (2, 2, 'Cover Two');
+ insert into item (id, gallery_id, title) values (4, 2, 'Item Four');
+ insert into item (id, gallery_id, title) values (5, 2, 'Item Five');
+ insert into item (id, gallery_id, title) values (6, 2, 'Item Six');");
+ foreach ($sql as $query) {
+ DB::execute ($query);
+ }
self::$q = new Qwerty ();
}
@@ -266,6 +314,20 @@ function test_batch () {
}));
$this->assertEquals (4, Foo::query ()->count ());
}
+
+ function test___call () {
+ $gallery = new Gallery (1);
+ $this->assertEquals ('Gallery One', $gallery->title);
+
+ $cover = $gallery->cover ();
+ $this->assertEquals ('Cover One', $cover->title);
+
+ $items = $gallery->items ();
+ $this->assertEquals (3, count ($items));
+ $this->assertEquals ('Item One', $items[0]->title);
+
+ $this->assertEquals ('Gallery One', $items[1]->gallery ()->cover ()->gallery ()->title);
+ }
}
?>
Please sign in to comment.
Something went wrong with that request. Please try again.