DboSource::queryAssociation PHP Method

queryAssociation() public method

Used to fetch results on recursive models. - 'hasMany' associations with no limit set: Fetch, filter and merge is done recursively for every level. - 'hasAndBelongsToMany' associations: Fetch and filter is done unaffected by the (recursive) level set.
public queryAssociation ( Model $Model, Model $LinkModel, string $type, string $association, array $assocData, &$queryData, boolean $external, &$resultSet, integer $recursive, array $stack ) : mixed
$Model Model Primary Model object.
$LinkModel Model Linked model object.
$type string Association type, one of the model association types ie. hasMany.
$association string Association name.
$assocData array Association data.
$external boolean Whether or not the association query is on an external datasource.
$recursive integer Number of levels of association.
$stack array A list with joined models.
return mixed
    public function queryAssociation(Model $Model, Model $LinkModel, $type, $association, $assocData, &$queryData, $external, &$resultSet, $recursive, $stack)
    {
        if (isset($stack['_joined'])) {
            $joined = $stack['_joined'];
            unset($stack['_joined']);
        }
        $queryTemplate = $this->generateAssociationQuery($Model, $LinkModel, $type, $association, $assocData, $queryData, $external);
        if (empty($queryTemplate)) {
            return;
        }
        if (!is_array($resultSet)) {
            throw new CakeException(__d('cake_dev', 'Error in Model %s', get_class($Model)));
        }
        if ($type === 'hasMany' && empty($assocData['limit']) && !empty($assocData['foreignKey'])) {
            // 'hasMany' associations with no limit set.
            $assocIds = array();
            foreach ($resultSet as $result) {
                $assocIds[] = $this->insertQueryData('{$__cakeID__$}', $result, $association, $Model, $stack);
            }
            $assocIds = array_filter($assocIds);
            // Fetch
            $assocResultSet = array();
            if (!empty($assocIds)) {
                $assocResultSet = $this->_fetchHasMany($Model, $queryTemplate, $assocIds);
            }
            // Recursively query associations
            if ($recursive > 0 && !empty($assocResultSet) && is_array($assocResultSet)) {
                foreach ($LinkModel->associations() as $type1) {
                    foreach ($LinkModel->{$type1} as $assoc1 => $assocData1) {
                        $DeepModel = $LinkModel->{$assoc1};
                        $tmpStack = $stack;
                        $tmpStack[] = $assoc1;
                        $db = $LinkModel->useDbConfig === $DeepModel->useDbConfig ? $this : $DeepModel->getDataSource();
                        $db->queryAssociation($LinkModel, $DeepModel, $type1, $assoc1, $assocData1, $queryData, true, $assocResultSet, $recursive - 1, $tmpStack);
                    }
                }
            }
            // Filter
            if ($queryData['callbacks'] === true || $queryData['callbacks'] === 'after') {
                $this->_filterResults($assocResultSet, $Model);
            }
            // Merge
            return $this->_mergeHasMany($resultSet, $assocResultSet, $association, $Model);
        } elseif ($type === 'hasAndBelongsToMany') {
            // 'hasAndBelongsToMany' associations.
            $assocIds = array();
            foreach ($resultSet as $result) {
                $assocIds[] = $this->insertQueryData('{$__cakeID__$}', $result, $association, $Model, $stack);
            }
            $assocIds = array_filter($assocIds);
            // Fetch
            $assocResultSet = array();
            if (!empty($assocIds)) {
                $assocResultSet = $this->_fetchHasAndBelongsToMany($Model, $queryTemplate, $assocIds, $association);
            }
            $habtmAssocData = $Model->hasAndBelongsToMany[$association];
            $foreignKey = $habtmAssocData['foreignKey'];
            $joinKeys = array($foreignKey, $habtmAssocData['associationForeignKey']);
            list($with, $habtmFields) = $Model->joinModel($habtmAssocData['with'], $joinKeys);
            $habtmFieldsCount = count($habtmFields);
            // Filter
            if ($queryData['callbacks'] === true || $queryData['callbacks'] === 'after') {
                $this->_filterResults($assocResultSet, $Model);
            }
        }
        $modelAlias = $Model->alias;
        $primaryKey = $Model->primaryKey;
        $selfJoin = $Model->name === $LinkModel->name;
        foreach ($resultSet as &$row) {
            if ($type === 'hasOne' || $type === 'belongsTo' || $type === 'hasMany') {
                $assocResultSet = array();
                if (($type === 'hasOne' || $type === 'belongsTo') && isset($row[$LinkModel->alias], $joined[$Model->alias]) && in_array($LinkModel->alias, $joined[$Model->alias])) {
                    $joinedData = Hash::filter($row[$LinkModel->alias]);
                    if (!empty($joinedData)) {
                        $assocResultSet[0] = array($LinkModel->alias => $row[$LinkModel->alias]);
                    }
                } else {
                    $query = $this->insertQueryData($queryTemplate, $row, $association, $Model, $stack);
                    if ($query !== false) {
                        $assocResultSet = $this->fetchAll($query, $Model->cacheQueries);
                    }
                }
            }
            if (!empty($assocResultSet) && is_array($assocResultSet)) {
                if ($recursive > 0) {
                    foreach ($LinkModel->associations() as $type1) {
                        foreach ($LinkModel->{$type1} as $assoc1 => $assocData1) {
                            $DeepModel = $LinkModel->{$assoc1};
                            if ($type1 === 'belongsTo' || $type === 'belongsTo' && $DeepModel->alias === $modelAlias || $DeepModel->alias !== $modelAlias) {
                                $tmpStack = $stack;
                                $tmpStack[] = $assoc1;
                                $db = $LinkModel->useDbConfig === $DeepModel->useDbConfig ? $this : $DeepModel->getDataSource();
                                $db->queryAssociation($LinkModel, $DeepModel, $type1, $assoc1, $assocData1, $queryData, true, $assocResultSet, $recursive - 1, $tmpStack);
                            }
                        }
                    }
                }
                if ($type === 'hasAndBelongsToMany') {
                    $merge = array();
                    foreach ($assocResultSet as $data) {
                        if (isset($data[$with]) && $data[$with][$foreignKey] === $row[$modelAlias][$primaryKey]) {
                            if ($habtmFieldsCount <= 2) {
                                unset($data[$with]);
                            }
                            $merge[] = $data;
                        }
                    }
                    if (empty($merge) && !isset($row[$association])) {
                        $row[$association] = $merge;
                    } else {
                        $this->_mergeAssociation($row, $merge, $association, $type);
                    }
                } else {
                    $this->_mergeAssociation($row, $assocResultSet, $association, $type, $selfJoin);
                }
                if ($type !== 'hasAndBelongsToMany' && isset($row[$association])) {
                    $row[$association] = $LinkModel->afterFind($row[$association], false);
                }
            } else {
                $tempArray[0][$association] = false;
                $this->_mergeAssociation($row, $tempArray, $association, $type, $selfJoin);
            }
        }
    }
DboSource