3 * TActiveRecordHasMany class file.
5 * @author Wei Zhuo <weizhuo[at]gmail[dot]com>
6 * @link https://github.com/pradosoft/prado
7 * @copyright Copyright © 2005-2016 The PRADO Group
8 * @license https://github.com/pradosoft/prado/blob/master/COPYRIGHT
10 * @package System.Data.ActiveRecord.Relations
14 * Loads base active record relations class.
16 Prado::using('System.Data.ActiveRecord.Relations.TActiveRecordRelation');
19 * Implements TActiveRecord::HAS_MANY relationship between the source object having zero or
20 * more foreign objects. Consider the <b>entity</b> relationship between a Team and a Player.
23 * | Team | 1 <----- * | Player |
26 * Where one team may have 0 or more players and each player belongs to only
27 * one team. We may model Team-Player <b>object</b> relationship as active record as follows.
29 * class TeamRecord extends TActiveRecord
32 * public $name; //primary key
35 * public $players=array(); //list of players
37 * public static $RELATIONS=array
39 * 'players' => array(self::HAS_MANY, 'PlayerRecord')
42 * public static function finder($className=__CLASS__)
44 * return parent::finder($className);
47 * class PlayerRecord extends TActiveRecord
49 * // see TActiveRecordBelongsTo for detailed definition
52 * The static <tt>$RELATIONS</tt> property of TeamRecord defines that the
53 * property <tt>$players</tt> has many <tt>PlayerRecord</tt>s.
55 * The players list may be fetched as follows.
57 * $team = TeamRecord::finder()->with_players()->findAll();
59 * The method <tt>with_xxx()</tt> (where <tt>xxx</tt> is the relationship property
60 * name, in this case, <tt>players</tt>) fetchs the corresponding PlayerRecords using
61 * a second query (not by using a join). The <tt>with_xxx()</tt> accepts the same
62 * arguments as other finder methods of TActiveRecord, e.g. <tt>with_players('age < ?', 35)</tt>.
64 * @author Wei Zhuo <weizho[at]gmail[dot]com>
66 * @package System.Data.ActiveRecord.Relations
69 class TActiveRecordHasMany extends TActiveRecordRelation
72 * Get the foreign key index values from the results and make calls to the
73 * database to find the corresponding foreign objects.
74 * @param array original results.
76 protected function collectForeignObjects(&$results)
78 $fkeys = $this->getRelationForeignKeys();
80 $properties = array_values($fkeys);
81 $fields = array_keys($fkeys);
83 $indexValues = $this->getIndexValues($properties, $results);
84 $fkObjects = $this->findForeignObjects($fields,$indexValues);
85 $this->populateResult($results,$properties,$fkObjects,$fields);
89 * @return array foreign key field names as key and object properties as value.
92 public function getRelationForeignKeys()
94 $fkObject = $this->getContext()->getForeignRecordFinder();
95 return $this->findForeignKeys($fkObject, $this->getSourceRecord());
99 * Updates the associated foreign objects.
100 * @return boolean true if all update are success (including if no update was required), false otherwise .
102 public function updateAssociatedRecords()
104 $obj = $this->getContext()->getSourceRecord();
105 $fkObjects = &$obj->{$this->getContext()->getProperty()};
107 if(($total = count($fkObjects))> 0)
109 $source = $this->getSourceRecord();
110 $fkeys = $this->findForeignKeys($fkObjects[0], $source);
111 for($i=0;$i<$total;$i++)
113 foreach($fkeys as $fKey => $srcKey)
114 $fkObjects[$i]->setColumnValue($fKey, $source->getColumnValue($srcKey));
115 $success = $fkObjects[$i]->save() && $success;