1<?php 2/** 3 * Doctrine_Ticket_749_TestCase 4 * 5 * @package Doctrine 6 * @author David Brewer <dbrewer@secondstory.com> 7 * @license http://www.opensource.org/licenses/lgpl-license.php LGPL 8 * @category Object Relational Mapping 9 * @link www.doctrine-project.org 10 * @since 1.0 11 * @version $Revision$ 12 * 13 * This test case demonstrates a problem with column aggregation inheritance 14 * in Doctrine 0.9. The high level summary is that it is possible to make 15 * it work in general -- if class B is a subclass of class A, you can select 16 * from class A and get back objects of class B. However, those objects do 17 * not have the related objects of class B, and in fact an exception is 18 * thrown when you try to access those related objects. 19 * 20 * This test case should not probably be applied to trunk and possibly not 21 * to 0.10 branch. I'm not sure it's even possible to fix in 0.9 but it is 22 * an issue that keeps arising for me so it seemed worth a test case. 23 */ 24 25class Doctrine_Ticket_749_TestCase extends Doctrine_UnitTestCase 26{ 27 public function prepareTables() 28 { 29 $this->tables = array('Parent749', 'Record749', 'RelatedRecord749'); 30 parent::prepareTables(); 31 } 32 33 public function prepareData() 34 { 35 $record = new Record749(); 36 $record['title'] = 'Test Record 1'; 37 $record['Related']['content'] = 'Test Content 1'; 38 $record->save(); 39 40 $record = new Record749(); 41 $record['title'] = 'Test Record 2'; 42 $record['Related']['content'] = 'Test Content 2'; 43 $record->save(); 44 } 45 46 public function testSelectDataFromSubclassAsCollection() 47 { 48 $records = Doctrine_Query::create()->query('FROM Record749 r ORDER BY r.title', array()); 49 50 $this->verifyRecords($records); 51 } 52 53 public function testSelectDataFromParentClassAsCollection() 54 { 55 56 $records = Doctrine_Query::create()->query('FROM Parent749 p ORDER BY p.title', array()); 57 $this->verifyRecords($records); 58 } 59 60 /** 61 * This method is used by both tests, as the collection of records should 62 * be identical for both of them if things are working properly. 63 */ 64 private function verifyRecords ($records) { 65 $expected_values = array( 66 array('title'=>'Test Record 1', 'content'=>'Test Content 1'), 67 array('title'=>'Test Record 2', 'content'=>'Test Content 2'), 68 ); 69 70 foreach ($records as $record) { 71 $this->assertTrue($record instanceof Record749); 72 $expected = array_shift($expected_values); 73 $this->assertEqual($record['title'], $expected['title']); 74 try { 75 $this->assertEqual($record['Related']['content'], $expected['content']); 76 } catch (Exception $e) { 77 $this->fail('Caught exception when trying to get related content: ' . $e->getMessage()); 78 } 79 } 80 } 81} 82 83class Parent749 extends Doctrine_Record 84{ 85 public function setTableDefinition() 86 { 87 $this->setTableName('mytable'); 88 $this->hasColumn('id', 'integer', 4, array ( 89 'primary' => true, 90 'autoincrement' => true, 91 'notnull' => true, 92 )); 93 94 $this->hasColumn('title', 'string', 255, array ()); 95 $this->hasColumn('type', 'integer', 11, array ()); 96 97 $this->setSubclasses(array('Record749' => array('type' => 1))); 98 } 99 100 public function setUp() 101 { 102 } 103} 104 105class Record749 extends Parent749 106{ 107 public function setTableDefinition() 108 { 109 parent::setTableDefinition(); 110 $this->setTableName('mytable'); 111 } 112 113 public function setUp() 114 { 115 parent::setUp(); 116 $this->hasOne('RelatedRecord749 as Related', array('local' => 'id', 117 'foreign' => 'record_id')); 118 } 119} 120 121class RelatedRecord749 extends Doctrine_Record 122{ 123 public function setTableDefinition() 124 { 125 $this->hasColumn('id', 'integer', 4, array ( 126 'primary' => true, 127 'autoincrement' => true, 128 'notnull' => true, 129 )); 130 131 $this->hasColumn('content', 'string', 255, array ()); 132 $this->hasColumn('record_id', 'integer', null, array ('unique' => true,)); 133 } 134 135 public function setUp() 136 { 137 $this->hasOne('Record749 as Record', array('local' => 'record_id', 138 'foreign' => 'id', 139 'onDelete' => 'cascade')); 140 } 141 142} 143 144