/** * Joins with another join element * @param CJoinElement $element the element to be joined */ public function join($element) { if ($element->slave !== null) { $this->join($element->slave); } if (!empty($element->relation->select)) { $this->selects[] = $element->getColumnSelect($element->relation->select); } $this->conditions[] = $element->relation->condition; $this->orders[] = $element->relation->order; $this->joins[] = $element->getJoinCondition(); $this->joins[] = $element->relation->join; $this->groups[] = $element->relation->group; $this->havings[] = $element->relation->having; if (is_array($element->relation->params)) { if (is_array($this->params)) { $this->params = array_merge($this->params, $element->relation->params); } else { $this->params = $element->relation->params; } } $this->elements[$element->id] = true; }
/** * Generates the join statement for many-many relationship. * @param CDbTableSchema $joinTable the join table * @param array $fks the foreign keys * @param CJoinElement $parent the parent join element * @return string the join statement * @throws CDbException if a foreign key is invalid */ private function joinManyMany($joinTable, $fks, $parent) { $schema = $this->_builder->getSchema(); $joinAlias = $schema->quoteTableName($this->relation->name . '_' . $this->tableAlias); $parentCondition = array(); $childCondition = array(); $fkDefined = true; foreach ($fks as $i => $fk) { if (!is_int($i)) { $pk = $fk; $fk = $i; } if (!isset($joinTable->columns[$fk])) { throw new CDbException(Yii::t('yii', 'The relation "{relation}" in active record class "{class}" is specified with an invalid foreign key "{key}". There is no such column in the table "{table}".', array('{class}' => get_class($parent->model), '{relation}' => $this->relation->name, '{key}' => $fk, '{table}' => $joinTable->name))); } if (is_int($i) && isset($joinTable->foreignKeys[$fk])) { list($tableName, $pk) = $joinTable->foreignKeys[$fk]; if (!isset($parentCondition[$pk]) && $schema->compareTableNames($parent->_table->rawName, $tableName)) { $parentCondition[$pk] = $parent->getColumnPrefix() . $schema->quoteColumnName($pk) . '=' . $joinAlias . '.' . $schema->quoteColumnName($fk); } elseif (!isset($childCondition[$pk]) && $schema->compareTableNames($this->_table->rawName, $tableName)) { $childCondition[$pk] = $this->getColumnPrefix() . $schema->quoteColumnName($pk) . '=' . $joinAlias . '.' . $schema->quoteColumnName($fk); } else { $fkDefined = false; break; } } else { $fkDefined = false; break; } } if (!$fkDefined) { $parentCondition = array(); $childCondition = array(); $fkNumber = 0; foreach ($fks as $i => $fk) { if (!is_int($i)) { $pk = $fk; $fk = $i; } if ($fkNumber < count($parent->_table->primaryKey)) { if (is_int($i)) { $pk = is_array($parent->_table->primaryKey) ? $parent->_table->primaryKey[$fkNumber] : $parent->_table->primaryKey; } $parentCondition[$pk] = $parent->getColumnPrefix() . $schema->quoteColumnName($pk) . '=' . $joinAlias . '.' . $schema->quoteColumnName($fk); } else { if (is_int($i)) { $j = $fkNumber - count($parent->_table->primaryKey); $pk = is_array($this->_table->primaryKey) ? $this->_table->primaryKey[$j] : $this->_table->primaryKey; } $childCondition[$pk] = $this->getColumnPrefix() . $schema->quoteColumnName($pk) . '=' . $joinAlias . '.' . $schema->quoteColumnName($fk); } $fkNumber++; } } if ($parentCondition !== array() && $childCondition !== array()) { $join = $this->relation->joinType . ' ' . $joinTable->rawName . ' ' . $joinAlias; $join .= ' ON (' . implode(') AND (', $parentCondition) . ')'; $join .= ' ' . $this->relation->joinType . ' ' . $this->getTableNameWithAlias(); $join .= ' ON (' . implode(') AND (', $childCondition) . ')'; if (!empty($this->relation->on)) { $join .= ' AND (' . $this->relation->on . ')'; } return $join; } else { throw new CDbException(Yii::t('yii', 'The relation "{relation}" in active record class "{class}" is specified with an incomplete foreign key. The foreign key must consist of columns referencing both joining tables.', array('{class}' => get_class($parent->model), '{relation}' => $this->relation->name))); } }