system system.base system.caching system.caching.dependencies system.collections system.console system.db system.db.ar system.db.schema system.db.schema.cubrid system.db.schema.mssql system.db.schema.mysql system.db.schema.oci system.db.schema.pgsql system.db.schema.sqlite system.gii system.i18n system.i18n.gettext system.logging system.test system.utils system.validators system.web system.web.actions system.web.auth system.web.filters system.web.form system.web.helpers system.web.renderers system.web.services system.web.widgets system.web.widgets.captcha system.web.widgets.pagers zii.behaviors zii.widgets zii.widgets.grid zii.widgets.jui

CJoinElement

system.db.ar
继承 class CJoinElement
可用自 1.0
源码 framework/db/ar/CActiveFinder.php
CJoinElement represents a tree node in the join tree created by CActiveFinder.

公共属性

隐藏继承的属性

属性类型描述被定义在
children array list of child join elements CJoinElement
id integer the unique ID of this tree node CJoinElement
master CActiveRelation the master relation CJoinElement
model CActiveRecord the model associated with this tree node CJoinElement
rawTableAlias string the quoted table alias for this element CJoinElement
records array list of active records found by the queries. CJoinElement
relation CActiveRelation the relation represented by this tree node CJoinElement
slave CActiveRelation the slave relation CJoinElement
stats array list of stat elements CJoinElement
tableAlias string table alias for this join element CJoinElement

公共方法

隐藏继承的方法

方法描述被定义在
__construct() Constructor. CJoinElement
afterFind() Calls CActiveRecord::afterFind of all the records. CJoinElement
buildQuery() Builds the join query with all descendant HAS_ONE and BELONGS_TO nodes. CJoinElement
count() Count the number of primary records returned by the join statement. CJoinElement
destroy() Removes references to child elements and finder to avoid circular references. CJoinElement
find() Performs the recursive finding with the criteria. CJoinElement
findWithBase() Performs the eager loading with the base records ready. CJoinElement
getColumnPrefix() Returns the column prefix for column reference disambiguation CJoinElement
getColumnSelect() Generates the list of columns to be selected. CJoinElement
getJoinCondition() Returns the join statement (this node joins with its parent) CJoinElement
getPrimaryKeyRange() Returns the condition that specifies only the rows with the selected primary key values. CJoinElement
getPrimaryKeySelect() Returns the primary key selection CJoinElement
getTableNameWithAlias() Returns the table name and the table alias (if any). This can be used directly in SQL query without escaping. CJoinElement
lazyFind() Performs lazy find with the specified base record. CJoinElement
runQuery() Executes the join query and populates the query results. CJoinElement

属性详情

children 属性
public array $children;

list of child join elements

id 属性
public integer $id;

the unique ID of this tree node

master 属性
public CActiveRelation $master;

the master relation

model 属性
public CActiveRecord $model;

the model associated with this tree node

rawTableAlias 属性
public string $rawTableAlias;

the quoted table alias for this element

records 属性
public array $records;

list of active records found by the queries. They are indexed by primary key values.

relation 属性
public CActiveRelation $relation;

the relation represented by this tree node

slave 属性
public CActiveRelation $slave;

the slave relation

stats 属性
public array $stats;

list of stat elements

tableAlias 属性
public string $tableAlias;

table alias for this join element

方法详情

__construct() 方法
public void __construct(CActiveFinder $finder, mixed $relation, CJoinElement $parent=NULL, integer $id=0)
$finder CActiveFinder the finder
$relation mixed the relation (if the third parameter is not null) or the model (if the third parameter is null) associated with this tree node.
$parent CJoinElement the parent tree node
$id integer the ID of this tree node that is unique among all the tree nodes
源码: framework/db/ar/CActiveFinder.php#375 (显示)
public function __construct($finder,$relation,$parent=null,$id=0)
{
    
$this->_finder=$finder;
    
$this->id=$id;
    if(
$parent!==null)
    {
        
$this->relation=$relation;
        
$this->_parent=$parent;
        
$this->model=$this->_finder->getModel($relation->className);
        
$this->_builder=$this->model->getCommandBuilder();
        
$this->tableAlias=$relation->alias===null?$relation->name:$relation->alias;
        
$this->rawTableAlias=$this->_builder->getSchema()->quoteTableName($this->tableAlias);
        
$this->_table=$this->model->getTableSchema();
    }
    else  
// root element, the first parameter is the model.
    
{
        
$this->model=$relation;
        
$this->_builder=$relation->getCommandBuilder();
        
$this->_table=$relation->getTableSchema();
        
$this->tableAlias=$this->model->getTableAlias();
        
$this->rawTableAlias=$this->_builder->getSchema()->quoteTableName($this->tableAlias);
    }

    
// set up column aliases, such as t1_c2
    
$table=$this->_table;
    if(
$this->model->getDbConnection()->getDriverName()==='oci')  // Issue 482
        
$prefix='T'.$id.'_C';
    else
        
$prefix='t'.$id.'_c';
    foreach(
$table->getColumnNames() as $key=>$name)
    {
        
$alias=$prefix.$key;
        
$this->_columnAliases[$name]=$alias;
        if(
$table->primaryKey===$name)
            
$this->_pkAlias=$alias;
        elseif(
is_array($table->primaryKey) && in_array($name,$table->primaryKey))
            
$this->_pkAlias[$name]=$alias;
    }
}

Constructor.

afterFind() 方法
public void afterFind()
源码: framework/db/ar/CActiveFinder.php#773 (显示)
public function afterFind()
{
    foreach(
$this->records as $record)
        
$record->afterFindInternal();
    foreach(
$this->children as $child)
        
$child->afterFind();

    
$this->children null;
}

Calls CActiveRecord::afterFind of all the records.

buildQuery() 方法
public void buildQuery(CJoinQuery $query)
$query CJoinQuery the query being built up
源码: framework/db/ar/CActiveFinder.php#787 (显示)
public function buildQuery($query)
{
    foreach(
$this->children as $child)
    {
        if(
$child->master!==null)
            
$child->_joined=true;
        elseif(
$child->relation instanceof CHasOneRelation || $child->relation instanceof CBelongsToRelation
            
|| $this->_finder->joinAll || $child->relation->together || (!$this->_finder->baseLimited && $child->relation->together===null))
        {
            
$child->_joined=true;
            
$query->join($child);
            
$child->buildQuery($query);
        }
    }
}

Builds the join query with all descendant HAS_ONE and BELONGS_TO nodes.

count() 方法
public string count(CDbCriteria $criteria=NULL)
$criteria CDbCriteria the query criteria
{return} string number of primary records. Note: type is string to keep max. precision.
源码: framework/db/ar/CActiveFinder.php#729 (显示)
public function count($criteria=null)
{
    
$query=new CJoinQuery($this,$criteria);
    
// ensure only one big join statement is used
    
$this->_finder->baseLimited=false;
    
$this->_finder->joinAll=true;
    
$this->buildQuery($query);

    
$query->limit=$query->offset=-1;

    if(!empty(
$criteria->group) || !empty($criteria->having))
    {
        
$query->orders = array();
        
$command=$query->createCommand($this->_builder);
        
$sql=$command->getText();
        
$sql="SELECT COUNT(*) FROM ({$sql}) sq";
        
$command->setText($sql);
        
$command->params=$query->params;
        return 
$command->queryScalar();
    }
    else
    {
        
$select=is_array($criteria->select) ? implode(',',$criteria->select) : $criteria->select;
        if(
$select!=='*' && preg_match('/^count\s*\(/i',trim($select)))
            
$query->selects=array($select);
        elseif(
is_string($this->_table->primaryKey))
        {
            
$prefix=$this->getColumnPrefix();
            
$schema=$this->_builder->getSchema();
            
$column=$prefix.$schema->quoteColumnName($this->_table->primaryKey);
            
$query->selects=array("COUNT(DISTINCT $column)");
        }
        else
            
$query->selects=array("COUNT(*)");

        
$query->orders=$query->groups=$query->havings=array();
        
$command=$query->createCommand($this->_builder);
        return 
$command->queryScalar();
    }
}

Count the number of primary records returned by the join statement.

destroy() 方法
public void destroy()
源码: framework/db/ar/CActiveFinder.php#419 (显示)
public function destroy()
{
    if(!empty(
$this->children))
    {
        foreach(
$this->children as $child)
            
$child->destroy();
    }
    unset(
$this->_finder$this->_parent$this->model$this->relation$this->master$this->slave$this->records$this->children$this->stats);
}

Removes references to child elements and finder to avoid circular references. This is internally used.

find() 方法
public void find(CDbCriteria $criteria=NULL)
$criteria CDbCriteria the query criteria
源码: framework/db/ar/CActiveFinder.php#433 (显示)
public function find($criteria=null)
{
    if(
$this->_parent===null// root element
    
{
        
$query=new CJoinQuery($this,$criteria);
        
$this->_finder->baseLimited=($criteria->offset>=|| $criteria->limit>=0);
        
$this->buildQuery($query);
        
$this->_finder->baseLimited=false;
        
$this->runQuery($query);
    }
    elseif(!
$this->_joined && !empty($this->_parent->records)) // not joined before
    
{
        
$query=new CJoinQuery($this->_parent);
        
$this->_joined=true;
        
$query->join($this);
        
$this->buildQuery($query);
        
$this->_parent->runQuery($query);
    }

    foreach(
$this->children as $child// find recursively
        
$child->find();

    foreach(
$this->stats as $stat)
        
$stat->query();
}

Performs the recursive finding with the criteria.

findWithBase() 方法
public void findWithBase(mixed $baseRecords)
$baseRecords mixed the available base record(s).
源码: framework/db/ar/CActiveFinder.php#693 (显示)
public function findWithBase($baseRecords)
{
    if(!
is_array($baseRecords))
        
$baseRecords=array($baseRecords);
    if(
is_string($this->_table->primaryKey))
    {
        foreach(
$baseRecords as $baseRecord)
            
$this->records[$baseRecord->{$this->_table->primaryKey}]=$baseRecord;
    }
    else
    {
        foreach(
$baseRecords as $baseRecord)
        {
            
$pk=array();
            foreach(
$this->_table->primaryKey as $name)
                
$pk[$name]=$baseRecord->$name;
            
$this->records[serialize($pk)]=$baseRecord;
        }
    }

    
$query=new CJoinQuery($this);
    
$this->buildQuery($query);
    if(
count($query->joins)>1)
        
$this->runQuery($query);
    foreach(
$this->children as $child)
        
$child->find();

    foreach(
$this->stats as $stat)
        
$stat->query();
}

Performs the eager loading with the base records ready.

getColumnPrefix() 方法
public string getColumnPrefix()
{return} string the column prefix for column reference disambiguation
源码: framework/db/ar/CActiveFinder.php#1021 (显示)
public function getColumnPrefix()
{
    if(
$this->tableAlias!==null)
        return 
$this->rawTableAlias.'.';
    else
        return 
$this->_table->rawName.'.';
}

getColumnSelect() 方法
public string getColumnSelect(mixed $select='*')
$select mixed columns to be selected. Defaults to '*', indicating all columns.
{return} string the column selection
源码: framework/db/ar/CActiveFinder.php#912 (显示)
public function getColumnSelect($select='*')
{
    
$schema=$this->_builder->getSchema();
    
$prefix=$this->getColumnPrefix();
    
$columns=array();
    if(
$select==='*')
    {
        foreach(
$this->_table->getColumnNames() as $name)
            
$columns[]=$prefix.$schema->quoteColumnName($name).' AS '.$schema->quoteColumnName($this->_columnAliases[$name]);
    }
    else
    {
        if(
is_string($select))
            
$select=explode(',',$select);
        
$selected=array();
        foreach(
$select as $name)
        {
            
$name=trim($name);
            
$matches=array();
            if((
$pos=strrpos($name,'.'))!==false)
                
$key=substr($name,$pos+1);
            else
                
$key=$name;
            
$key=trim($key,'\'"`');

            if(
$key==='*')
            {
                foreach(
$this->_table->columns as $name=>$column)
                {
                    
$alias=$this->_columnAliases[$name];
                    if(!isset(
$selected[$alias]))
                    {
                        
$columns[]=$prefix.$column->rawName.' AS '.$schema->quoteColumnName($alias);
                        
$selected[$alias]=1;
                    }
                }
                continue;
            }

            if(isset(
$this->_columnAliases[$key]))  // simple column names
            
{
                
$columns[]=$prefix.$schema->quoteColumnName($key).' AS '.$schema->quoteColumnName($this->_columnAliases[$key]);
                
$selected[$this->_columnAliases[$key]]=1;
            }
            elseif(
preg_match('/^(.*?)\s+AS\s+(\w+)$/im',$name,$matches)) // if the column is already aliased
            
{
                
$alias=$matches[2];
                if(!isset(
$this->_columnAliases[$alias]) || $this->_columnAliases[$alias]!==$alias)
                {
                    
$this->_columnAliases[$alias]=$alias;
                    
$columns[]=$name;
                    
$selected[$alias]=1;
                }
            }
            else
                throw new 
CDbException(Yii::t('yii','Active record "{class}" is trying to select an invalid column "{column}". Note, the column must exist in the table or be an expression with alias.',
                    array(
'{class}'=>get_class($this->model), '{column}'=>$name)));
        }
        
// add primary key selection if they are not selected
        
if(is_string($this->_pkAlias) && !isset($selected[$this->_pkAlias]))
            
$columns[]=$prefix.$schema->quoteColumnName($this->_table->primaryKey).' AS '.$schema->quoteColumnName($this->_pkAlias);
        elseif(
is_array($this->_pkAlias))
        {
            foreach(
$this->_pkAlias as $name=>$alias)
                if(!isset(
$selected[$alias]))
                    
$columns[]=$prefix.$schema->quoteColumnName($name).' AS '.$schema->quoteColumnName($alias);
        }
    }

    return 
implode(', ',$columns);
}

Generates the list of columns to be selected. Columns will be properly aliased and primary keys will be added to selection if they are not specified.

getJoinCondition() 方法
public string getJoinCondition()
{return} string the join statement (this node joins with its parent)
源码: framework/db/ar/CActiveFinder.php#1033 (显示)
public function getJoinCondition()
{
    
$parent=$this->_parent;
    if(
$this->relation instanceof CManyManyRelation)
    {
        
$schema=$this->_builder->getSchema();
        
$joinTableName=$this->relation->getJunctionTableName();
        if((
$joinTable=$schema->getTable($joinTableName))===null)
            throw new 
CDbException(Yii::t('yii','The relation "{relation}" in active record class "{class}" is not specified correctly: the join table "{joinTable}" given in the foreign key cannot be found in the database.',
                array(
'{class}'=>get_class($parent->model), '{relation}'=>$this->relation->name'{joinTable}'=>$joinTableName)));
        
$fks=$this->relation->getJunctionForeignKeys();

        return 
$this->joinManyMany($joinTable,$fks,$parent);
    }
    else
    {
        
$fks=is_array($this->relation->foreignKey) ? $this->relation->foreignKey preg_split('/\s*,\s*/',$this->relation->foreignKey,-1,PREG_SPLIT_NO_EMPTY);
        if(
$this->slave!==null)
        {
            if(
$this->relation instanceof CBelongsToRelation)
            {
                
$fks=array_flip($fks);
                
$pke=$this->slave;
                
$fke=$this;
            }
            else
            {
                
$pke=$this;
                
$fke=$this->slave;
            }
        }
        elseif(
$this->relation instanceof CBelongsToRelation)
        {
            
$pke=$this;
            
$fke=$parent;
        }
        else
        {
            
$pke=$parent;
            
$fke=$this;
        }
        return 
$this->joinOneMany($fke,$fks,$pke,$parent);
    }
}

getPrimaryKeyRange() 方法
public string getPrimaryKeyRange()
{return} string the condition that specifies only the rows with the selected primary key values.
源码: framework/db/ar/CActiveFinder.php#1005 (显示)
public function getPrimaryKeyRange()
{
    if(empty(
$this->records))
        return 
'';
    
$values=array_keys($this->records);
    if(
is_array($this->_table->primaryKey))
    {
        foreach(
$values as &$value)
            
$value=unserialize($value);
    }
    return 
$this->_builder->createInCondition($this->_table,$this->_table->primaryKey,$values,$this->getColumnPrefix());
}

getPrimaryKeySelect() 方法
public string getPrimaryKeySelect()
{return} string the primary key selection
源码: framework/db/ar/CActiveFinder.php#987 (显示)
public function getPrimaryKeySelect()
{
    
$schema=$this->_builder->getSchema();
    
$prefix=$this->getColumnPrefix();
    
$columns=array();
    if(
is_string($this->_pkAlias))
        
$columns[]=$prefix.$schema->quoteColumnName($this->_table->primaryKey).' AS '.$schema->quoteColumnName($this->_pkAlias);
    elseif(
is_array($this->_pkAlias))
    {
        foreach(
$this->_pkAlias as $name=>$alias)
            
$columns[]=$prefix.$schema->quoteColumnName($name).' AS '.$schema->quoteColumnName($alias);
    }
    return 
implode(', ',$columns);
}

getTableNameWithAlias() 方法
public string getTableNameWithAlias()
{return} string the table name and the table alias (if any). This can be used directly in SQL query without escaping.
源码: framework/db/ar/CActiveFinder.php#897 (显示)
public function getTableNameWithAlias()
{
    if(
$this->tableAlias!==null)
        return 
$this->_table->rawName ' ' $this->rawTableAlias;
    else
        return 
$this->_table->rawName;
}

lazyFind() 方法
public void lazyFind(CActiveRecord $baseRecord)
$baseRecord CActiveRecord the active record whose related object is to be fetched.
源码: framework/db/ar/CActiveFinder.php#463 (显示)
public function lazyFind($baseRecord)
{
    if(
is_string($this->_table->primaryKey))
        
$this->records[$baseRecord->{$this->_table->primaryKey}]=$baseRecord;
    else
    {
        
$pk=array();
        foreach(
$this->_table->primaryKey as $name)
            
$pk[$name]=$baseRecord->$name;
        
$this->records[serialize($pk)]=$baseRecord;
    }

    foreach(
$this->stats as $stat)
        
$stat->query();

    if(!
$this->children)
        return;

    
$params=array();
    foreach(
$this->children as $child)
        if(
is_array($child->relation->params))
            
$params=array_merge($params,$child->relation->params);

    
$query=new CJoinQuery($child);
    
$query->selects=array($child->getColumnSelect($child->relation->select));
    
$query->conditions=array(
        
$child->relation->on,
    );
    
$query->groups[]=$child->relation->group;
    
$query->joins[]=$child->relation->join;
    
$query->havings[]=$child->relation->having;
    
$query->orders[]=$child->relation->order;
    
$query->params=$params;
    
$query->elements[$child->id]=true;
    if(
$child->relation instanceof CHasManyRelation)
    {
        
$query->limit=$child->relation->limit;
        
$query->offset=$child->relation->offset;
    }

    
$child->applyLazyCondition($query,$baseRecord);

    
$this->_joined=true;
    
$child->_joined=true;

    
$this->_finder->baseLimited=false;
    
$child->buildQuery($query);
    
$child->runQuery($query);
    foreach(
$child->children as $c)
        
$c->find();

    if(empty(
$child->records))
        return;
    if(
$child->relation instanceof CHasOneRelation || $child->relation instanceof CBelongsToRelation)
        
$baseRecord->addRelatedRecord($child->relation->name,reset($child->records),false);
    else 
// has_many and many_many
    
{
        foreach(
$child->records as $record)
        {
            if(
$child->relation->index!==null)
                
$index=$record->{$child->relation->index};
            else
                
$index=true;
            
$baseRecord->addRelatedRecord($child->relation->name,$record,$index);
        }
    }
}

Performs lazy find with the specified base record.

runQuery() 方法
public void runQuery(CJoinQuery $query)
$query CJoinQuery the query to be executed.
源码: framework/db/ar/CActiveFinder.php#807 (显示)
public function runQuery($query)
{
    
$command=$query->createCommand($this->_builder);
    foreach(
$command->queryAll() as $row)
        
$this->populateRecord($query,$row);
}

Executes the join query and populates the query results.