diff --git a/lib/Doctrine/Table.php b/lib/Doctrine/Table.php
index 96108f0d5..70d958320 100644
--- a/lib/Doctrine/Table.php
+++ b/lib/Doctrine/Table.php
@@ -1145,13 +1145,53 @@ class Doctrine_Table extends Doctrine_Configurable implements Countable
if (isset($this->identityMap[$id])) {
$record = $this->identityMap[$id];
} else {
- $record = new $this->options['name']($this);
+ $recordName = $this->getClassnameToReturn();
+ $record = new $recordName($this);
$this->identityMap[$id] = $record;
}
$this->data = array();
return $record;
}
+
+ /**
+ * Get the classname to return. Most often this is just the options['name']
+ *
+ * Check the subclasses option and the inheritanceMap for each subclass to see
+ * if all the maps in a subclass is met. If this is the case return that
+ * subclass name. If no subclasses match or if there are no subclasses defined
+ * return the name of the class for this tables record.
+ *
+ * @todo this function could use reflection to check the first time it runs
+ * if the subclassing option is not set.
+ *
+ * @return string The name of the class to create
+ *
+ */
+ public function getClassnameToReturn()
+ {
+ if(!isset($this->options["subclasses"])){
+ return $this->options['name'];
+ }
+ foreach($this->options["subclasses"] as $subclass){
+ $table = $this->conn->getTable($subclass);
+ $inheritanceMap = $table->getOption("inheritanceMap");
+ $nomatch = false;
+ foreach($inheritanceMap as $key => $value){
+ if(!isset($this->data[$key]) || $this->data[$key] != $value){
+ $nomatch = true;
+ break;
+ }
+ }
+ if(!$nomatch){
+ return $table->getComponentName();
+ }
+ }
+ return $this->options['name'];
+ }
+
+
+
/**
* @param $id database row id
* @throws Doctrine_Find_Exception
diff --git a/manual/codes/Object relational mapping - Relations - Inheritance - Column aggregation.php b/manual/codes/Object relational mapping - Relations - Inheritance - Column aggregation.php
deleted file mode 100644
index 56e56b7d9..000000000
--- a/manual/codes/Object relational mapping - Relations - Inheritance - Column aggregation.php
+++ /dev/null
@@ -1,26 +0,0 @@
-hasColumn("name","string",30);
- $this->hasColumn("username","string",20);
- $this->hasColumn("password","string",16);
- $this->hasColumn("created","integer",11);
-
- // this column is used for column
- // aggregation inheritance
- $this->hasColumn("type", "integer", 11);
- }
-}
-
-class User extends Entity {
- public function setUp() {
- $this->setInheritanceMap(array("type"=>1));
- }
-}
-
-class Group extends Entity {
- public function setUp() {
- $this->setInheritanceMap(array("type"=>2));
- }
-}
-?>
diff --git a/manual/docs/Object relational mapping - Relations - Inheritance - Column aggregation.php b/manual/docs/Object relational mapping - Relations - Inheritance - Column aggregation.php
index 8d399c14c..ee7969fe3 100644
--- a/manual/docs/Object relational mapping - Relations - Inheritance - Column aggregation.php
+++ b/manual/docs/Object relational mapping - Relations - Inheritance - Column aggregation.php
@@ -1,8 +1,87 @@
-In the following example we have one database table called 'entity'.
-Users and groups are both entities and they share the same database table.
-
-The entity table has a column called 'type' which tells whether an entity is a group or a user.
-Then we decide that users are type 1 and groups type 2.
+In the following example we have one database table called 'entity'. Users and groups are both entities and they share the same database table.
+
+The entity table has a column called 'type' which tells whether an entity is a group or a user. Then we decide that users are type 1 and groups type 2.
+
+The only thing we have to do is to create 3 records (the same as before) and add call the Doctrine_Table::setInheritanceMap() method inside the setUp() method.
+
+
+class Entity extends Doctrine_Record {
+ public function setTableDefinition() {
+ $this->hasColumn("name","string",30);
+ $this->hasColumn("username","string",20);
+ $this->hasColumn("password","string",16);
+ $this->hasColumn("created","integer",11);
+
+ // this column is used for column
+ // aggregation inheritance
+ $this->hasColumn("type", "integer", 11);
+ }
+}
+
+class User extends Entity {
+ public function setUp() {
+ $this->setInheritanceMap(array("type"=>1));
+ }
+}
+
+class Group extends Entity {
+ public function setUp() {
+ $this->setInheritanceMap(array("type"=>2));
+ }
+}
+
+
+If we want to be able to fetch a record from the Entity table and automatically get a User record if the Entity we fetched is a user we have to do set the subclasses option in the parent class. The adjusted example:
+
+
+class Entity extends Doctrine_Record {
+ public function setTableDefinition() {
+ $this->hasColumn("name","string",30);
+ $this->hasColumn("username","string",20);
+ $this->hasColumn("password","string",16);
+ $this->hasColumn("created","integer",11);
+
+ // this column is used for column
+ // aggregation inheritance
+ $this->hasColumn("type", "integer", 11);
+ $this->option("subclasses", array("User", "Group");
+ }
+}
+
+class User extends Entity {
+ public function setUp() {
+ $this->setInheritanceMap(array("type"=>1));
+ }
+}
+
+class Group extends Entity {
+ public function setUp() {
+ $this->setInheritanceMap(array("type"=>2));
+ }
+}
+
+
+We can then do the following given the previous table mapping.
+
+
+$user = new User();
+$user->name="Bjarte S. Karlsen";
+$user->username="meus";
+$user->password="rat";
+$user->save();
+
+$group = new Group();
+$group->name="Users";
+$group->username="users";
+$group->password="password";
+$group->save();
+
+$q = Doctrine_Query();
+$user = $q->from("Entity")->where("id=?")->execute(array($user->id))->getFirst();
+
+$q = Doctrine_Query();
+$group = $q->from("Entity")->where("id=?")->execute(array($group->id))->getFirst();
+
+
+The user object is here an instance of User while the group object is an instance of Group.
-The only thing we have to do is to create 3 records (the same as before) and add
-call the Doctrine_Table::setInheritanceMap() method inside the setUp() method.
diff --git a/tests/ColumnAggregationInheritanceTestCase.php b/tests/ColumnAggregationInheritanceTestCase.php
new file mode 100644
index 000000000..6df43b9d9
--- /dev/null
+++ b/tests/ColumnAggregationInheritanceTestCase.php
@@ -0,0 +1,67 @@
+.
+ */
+
+/**
+ * Doctrine_ColumnAlias_TestCase
+ *
+ * @package Doctrine
+ * @author Bjarte Stien Karlsen
+ * @license http://www.opensource.org/licenses/lgpl-license.php LGPL
+ * @category Object Relational Mapping
+ * @link www.phpdoctrine.com
+ * @since 1.0
+ * @version $Revision$
+ */
+class Doctrine_ColumnAggregationInheritance_TestCase extends Doctrine_UnitTestCase
+{
+ protected $otherEntity = null;
+
+ public function prepareData()
+ {
+
+ parent::prepareData();
+ //we create a test entity that is not a user and not a group
+ $entity = new Entity();
+ $entity->name="Other Entity";
+ $entity->type = 2;
+ $entity->save();
+ $this->otherEntity = $entity;
+ }
+
+ public function testQueriedClassReturnedIfNoSubclassMatch()
+ {
+ $q = new Doctrine_Query();
+ $entityOther = $q->from("Entity")->where("id=?")->execute(array($this->otherEntity->id))->getFirst();
+ $this->assertTrue($entityOther instanceOf Entity);
+ }
+
+ public function testSubclassReturnedIfInheritanceMatches()
+ {
+ $q = new Doctrine_Query();
+ $group = $q->from("Entity")->where("id=?")->execute(array(1))->getFirst();
+ $this->assertTrue($group instanceOf Group);
+
+ $q = new Doctrine_Query();
+ $user = $q->from("Entity")->where("id=?")->execute(array(5))->getFirst();
+ $this->assertTrue($user instanceOf User);
+ }
+}
+
diff --git a/tests/classes.php b/tests/classes.php
index 59786c4af..505662c83 100644
--- a/tests/classes.php
+++ b/tests/classes.php
@@ -15,6 +15,7 @@ class Entity extends Doctrine_Record {
$this->hasColumn('created', 'integer',11);
$this->hasColumn('updated', 'integer',11);
$this->hasColumn('email_id', 'integer');
+ $this->option('subclasses',array('User','Group'));
}
}
class FieldNameTest extends Doctrine_Record {
diff --git a/tests/run.php b/tests/run.php
index a24c7b373..24e1a158e 100644
--- a/tests/run.php
+++ b/tests/run.php
@@ -222,6 +222,7 @@ $test->addTestCase(new Doctrine_Query_Having_TestCase());
$test->addTestCase(new Doctrine_Query_From_TestCase());
$test->addTestCase(new Doctrine_Query_JoinCondition_TestCase());
$test->addTestCase(new Doctrine_ColumnAlias_TestCase());
+$test->addTestCase(new Doctrine_ColumnAggregationInheritance_TestCase());
$test->addTestCase(new Doctrine_Query_Subquery_TestCase());
$test->addTestCase(new Doctrine_Query_Join_TestCase());
@@ -239,6 +240,7 @@ $test->addTestCase(new Doctrine_Cache_Sqlite_TestCase());
//$test->addTestCase(new Doctrine_Cache_FileTestCase());
//$test->addTestCase(new Doctrine_Cache_SqliteTestCase());
+
class MyReporter extends HtmlReporter {
public function paintHeader() {}
public function paintFooter()