public function getRelationalRecords($key, $relation = null)
{
// check for the object cache
$cacheKey = 'relationship::' . $key;
if ($this->hasInternalCache($cacheKey)) {
return clone $this->_cache[$cacheKey];
}
if (!$relation) {
$relation = $this->getSchema()->getRelation($key);
}
/*
switch($relation['type']) {
case Relationship::HAS_ONE:
case Relationship::HAS_MANY:
break;
}
*/
if (Relationship::HAS_ONE === $relation['type']) {
$sColumn = $relation['self_column'];
$fSchema = $relation->newForeignSchema();
$fColumn = $relation['foreign_column'];
if (!$this->hasValue($sColumn)) {
return;
}
// throw new Exception("The value of $sColumn of " . get_class($this) . ' is not defined.');
$sValue = $this->getValue($sColumn);
$model = $relation->newForeignModel();
$model->load(array($fColumn => $sValue));
return $this->setInternalCache($cacheKey, $model);
} elseif (Relationship::HAS_MANY === $relation['type']) {
// TODO: migrate this code to Relationship class.
$sColumn = $relation['self_column'];
$fSchema = $relation->newForeignSchema();
$fColumn = $relation['foreign_column'];
if (!$this->hasValue($sColumn)) {
return;
}
// throw new Exception("The value of $sColumn of " . get_class($this) . ' is not defined.');
$sValue = $this->getValue($sColumn);
$collection = $relation->getForeignCollection();
$collection->where()->equal($collection->getAlias() . '.' . $fColumn, $sValue);
// where 'm' is the default alias.
// For if we need to create relational records
// though collection object, we need to pre-set
// the relational record id.
$collection->setPresetVars(array($fColumn => $sValue));
return $this->setInternalCache($cacheKey, $collection);
} elseif (Relationship::BELONGS_TO === $relation['type']) {
$sColumn = $relation['self_column'];
$fSchema = $relation->newForeignSchema();
$fColumn = $relation['foreign_column'];
$fpSchema = SchemaLoader::load($fSchema->getSchemaProxyClass());
if (!$this->hasValue($sColumn)) {
return;
}
$sValue = $this->getValue($sColumn);
$model = $fpSchema->newModel();
$ret = $model->load(array($fColumn => $sValue));
return $this->setInternalCache($cacheKey, $model);
} elseif (Relationship::MANY_TO_MANY === $relation['type']) {
$rId = $relation['relation_junction'];
// use relationId to get middle relation. (author_books)
$rId2 = $relation['relation_foreign'];
// get external relationId from the middle relation. (book from author_books)
$middleRelation = $this->getSchema()->getRelation($rId);
if (!$middleRelation) {
throw new InvalidArgumentException("first level relationship of many-to-many {$rId} is empty");
}
// eg. author_books
$sColumn = $middleRelation['foreign_column'];
$sSchema = $middleRelation->newForeignSchema();
$spSchema = SchemaLoader::load($sSchema->getSchemaProxyClass());
$foreignRelation = $spSchema->getRelation($rId2);
if (!$foreignRelation) {
throw new InvalidArgumentException("second level relationship of many-to-many {$rId2} is empty.");
}
$fSchema = $foreignRelation->newForeignSchema();
$fColumn = $foreignRelation['foreign_column'];
$fpSchema = SchemaLoader::load($fSchema->getSchemaProxyClass());
$collection = $fpSchema->newCollection();
/*
* join middle relation ship
*
* Select * from books b (r2) left join author_books ab on ( ab.book_id = b.id )
* where b.author_id = :author_id
*/
$collection->join($sSchema->getTable())->as('b')->on()->equal('b.' . $foreignRelation['self_column'], array($collection->getAlias() . '.' . $fColumn));
$value = $this->getValue($middleRelation['self_column']);
$collection->where()->equal('b.' . $middleRelation['foreign_column'], $value);
/*
* for many-to-many creation:
*
* $author->books[] = array(
* ':author_books' => array( 'created_on' => date('c') ),
* 'title' => 'Book Title',
* );
*/
$collection->setPostCreate(function ($record, $args) use($spSchema, $rId, $middleRelation, $foreignRelation, $value) {
// arguments for creating middle-relationship record
$a = array($foreignRelation['self_column'] => $record->getValue($foreignRelation['foreign_column']), $middleRelation['foreign_column'] => $value);
if (isset($args[':' . $rId])) {
$a = array_merge($args[':' . $rId], $a);
}
// create relationship
$middleRecord = $spSchema->newModel();
$ret = $middleRecord->create($a);
if (!$ret->success) {
throw new Exception("{$rId} create failed.");
}
return $middleRecord;
});
return $this->setInternalCache($cacheKey, $collection);
}
throw new Exception("The relationship type of {$key} is not supported.");
}