Join eager loaded relation and get the related column name.

@param string $relation
@param string $relationColumn
@return string
504859
protected function joinEagerLoadedColumn($relation, $relationColumn)
    {
        $joins = [];
        foreach ((array) $this->getQueryBuilder()->joins as $key => $join) {
            $joins[] = $join->table;
        }

        $model = $this->query->getRelation($relation);
        if ($model instanceof BelongsToMany) {
            $pivot   = $model->getTable();
            $pivotPK = $model->getForeignKey();
            $pivotFK = $model->getQualifiedParentKeyName();

            if (!in_array($pivot, $joins)) {
                $this->getQueryBuilder()->leftJoin($pivot, $pivotPK, '=', $pivotFK);
            }

            $related = $model->getRelated();
            $table   = $related->getTable();
            $tablePK = $related->getForeignKey();
            $tableFK = $related->getQualifiedKeyName();

            if (!in_array($table, $joins)) {
                $this->getQueryBuilder()->leftJoin($table, $pivot . '.' . $tablePK, '=', $tableFK);
            }
        } else {
            $table   = $model->getRelated()->getTable();
            $foreign = $model->getQualifiedForeignKey();
            $other   = $model->getQualifiedOtherKeyName();
            if (!in_array($table, $joins)) {
                $this->getQueryBuilder()->leftJoin($table, $foreign, '=', $other);
            }
        }

        $column = $table . '.' . $relationColumn;

        return $column;
    }
198493
public static function getRelationGridColumns($model, $fields, $relationName, $relation)
    {
        $columns = parent::getRelationGridColumns($model, $fields, $relationName, $relation);
        $controller = Yii::$app->crudModelsMap[$model::className()];
        $actionColumn = new \yii\grid\ActionColumn();

        if (!isset($columns[0]) || !isset($columns[0]['class']) || $columns[0]['class'] !== 'yii\grid\ActionColumn') {
            array_unshift($columns, [
                'class'         => 'yii\grid\ActionColumn',
                'headerOptions' => ['class' => 'column-action'],
                'controller'    => $controller,
                'template'      => '',
                'buttons'       => [],
            ]);
        }

        $columns[0]['template'] = '{update} {unlink}';
        $columns[0]['urlCreator'] = function ($action, $model, $key, $index) use ($controller, $relation) {
            $params = is_array($key) ? $key : ['id' => (string)$key];
            if ($action === 'update') {
                $params['hide'] = implode(',', array_keys($relation->link));
            }
            $params[0] = $controller . '/' . $action;

            return Url::toRoute($params);
        };
        $columns[0]['buttons']['update'] = function ($url, $model, $key) use ($actionColumn, $relationName) {
            /** @var \netis\crud\db\ActiveRecord $model */
            if (!Yii::$app->user->can($model::className() . '.update', ['model' => $model])) {
                return null;
            }

            $options = array_merge([
                'title'         => Yii::t('app', 'Update'),
                'aria-label'    => Yii::t('app', 'Update'),
                'data-pjax'     => '0',
                // required for editing in a modal
                'data-toggle'   => 'modal',
                'data-target'   => '#relationModal',
                'data-relation' => $relationName,
                'data-title'    => $model->getCrudLabel('update'),
                'data-pjax-url' => $url,
                'class'         => 'btn btn-default btn-xs',
            ], $actionColumn->buttonOptions);
            return Html::a('<span class="glyphicon glyphicon-pencil"></span>', $url, $options);
        };

        /** @var \yii\db\ActiveQuery $relation */
        $remove = false;
        $modelClass = $relation->modelClass;
        foreach (array_keys($relation->link) as $foreignKey) {
            $remove = $remove || !$modelClass::getTableSchema()->getColumn($foreignKey)->allowNull;
        }

        $columns[0]['buttons']['unlink'] = function ($url, $model, $key) use ($actionColumn, $remove) {
            /** @var \netis\crud\db\ActiveRecord $model */
            if (!Yii::$app->user->can($model::className() . ($remove ? '.delete' : '.update'), ['model' => $model])) {
                return null;
            }

            $options = array_merge([
                'title'      => Yii::t('app', 'Unlink'),
                'aria-label' => Yii::t('app', 'Unlink'),
                //'data-confirm' => Yii::t('app', 'Are you sure you want to unlink this item?'),
                'data-pjax'  => '0',
                'class'      => 'remove btn btn-default btn-xs',
            ], $actionColumn->buttonOptions);
            return Html::a('<span class="glyphicon glyphicon-remove"></span>', $url, $options);
        };
        return $columns;
    }
216899
public function applyToRelation(BelongsToMany $relation)
    {
        $this->applyToRelationQuery(
            $relation->getQuery(),
            $relation->getTable()
        );

        return $relation;
    }
1197439
public function loadMorph($relation, $relations)
    {
        $this->pluck($relation)
            ->filter()
            ->groupBy(function ($model) {
                return get_class($model);
            })
            ->each(function ($models, $className) use ($relations) {
                static::make($models)->load($relations[$className] ?? []);
            });

        return $this;
    }
1285819
public static function buildRelationQuery($entity, Relation $relation) {
        $relQuery = "";
        $getid = "getId";
        if ($relation->getCardinality() == Relation::$manyToMany) {
            $m = "get" . $relation->getName();
            $relQuery .= "INSERT INTO " . $relation->getTable() . " (" . $relation->getLocalColumn() . ", " . $relation->getForeignColumn() . ") ";
            $relQuery .= "VALUES (:" . $relation->getLocalColumn() . ", :" . $relation->getForeignColumn() . ");";
        }
        if ($relation->getCardinality() == Relation::$oneToMany) {
            $relMapper = MapperBuilder::buildFromName($this->mapping, $relation->getEntity());
            $m = "get" . $relation->getName();
            foreach ($entity->$m() as $rel) {
                $setid = "set" . $relMapper->getNameForColumn($relation->getForeignColumn());
                $rel->$setid($entity->$getid());
                $relQuery .= $this->buildInsertQuery($rel);
            }
        }


        return $relQuery;
    }
522531
public function getLink($relation)
    {
        $links = $this->getAllLinks();
        foreach ($links as $link) {
            if ($link->getRelation() === $relation) {
                return $link;
            }
        }

        return null;
    }
797280
private function processParentRelation(Schema\Relation $relation)
    {
        $prefixRegex = '/^'.preg_quote($this->name, '/').'\.(\d+\.)*(?P<sub>.*)/';
        if (!preg_match($prefixRegex, $relation->getLocalProperty(), $matches)) {
            return null;
        }

        $clone = clone $relation;
        $clone->setLocalProperty($matches['sub']);
        return $clone;
    }
1302235
public function getRelationTableName($relation) {
        $relationTable  = !empty($this->tablePrefix) ? $this->tablePrefix : '';
        $relationTable .= $this->tableName?$this->tableName:$this->name;
        $relationTable .= '_'.$relation->getModelName();
        return strtolower($relationTable);
    }
499176
public function addJoinColumn(
        $relation,
        $joinColumn = null,
        $referenceColumn = null,
        $nullable = false,
        $unique = false,
        $onDelete = null,
        $columnDefinition = null
    ) {
        $joinColumn = new JoinColumn(
            $this->getNamingStrategy(),
            $relation,
            $joinColumn,
            $referenceColumn,
            $nullable,
            $unique,
            $onDelete,
            $columnDefinition
        );

        $this->pushJoinColumn($joinColumn);

        return $this;
    }
789311
public function getRelation($relation)
    {
        $query = Relation::noConstraints(function() use ($relation)
        {
            return $this->getModel()->$relation();
        });

        $nested = $this->nestedRelations($relation);

        if (count($nested) > 0) {
            $query->getQuery()->with($nested);
        }

        return $query;
    }
431755
public function getRelationLabel($activeRelation, $relation)
    {
        $modelClass = $activeRelation->modelClass;
        if (isset($this->cachedRelationLabels[$modelClass][$relation])) {
            return $this->cachedRelationLabels[$modelClass][$relation];
        }
        if (isset($this->relationLabels[$relation])) {
            $label = $this->relationLabels[$relation];
        } else {
            /** @var ActiveRecord $relationModel */
            $relationModel = new $modelClass;
            $label = $relationModel->getCrudLabel($activeRelation->multiple ? 'relation' : 'default');
        }
        return $this->cachedRelationLabels[$modelClass][$relation] = $label;
    }
866813
public function relation($relationName) {
		if(!$this->dataMapper->hasRelation($this->definition, $relationName))
			throw new \Exception('Relation '.$relationName.' does not exist.');
		$relation = $this->dataMapper->relation($this->definition, $relationName);
		$reverseRelation = $relation->reverse();
		$reverseRelationName = $reverseRelation->get('name');
		$relation_entity = $relation->get('entity');

		$table = $this->getTable();
		$alias = $reverseRelationName;

		$c = clone $this;
		$c->applyScopes();

		$where = $this->processConditions($c->getWhere());
		$where = $this->updateConditions($where, $table, $alias);

		return $this->dataMapper->orm($relation_entity)
			->where($where)
			->join('innerjoin '.$reverseRelationName, $this->join);
	}
1057476
public function findRelation($entity, $relationName, $orderColumn = null, $orderType = null) {
        $this->load();
        $mapper = MapperBuilder::buildFromClassName($this->mapping, get_class($entity));
        $relation = $mapper->getRelation($relationName);
        $relationMapper = MapperBuilder::buildFromName($this->mapping, $relation->getEntity());

        $selectQuery = "SELECT tmain.* FROM `" . $relationMapper->getTable() . "` tmain ";
        $joinQuery = QueryBuilder::buildJoinRelationQuery($relation, "tmain", "j1");
        $whereQuery = "WHERE j1." . $relation->getLocalColumn() . " = '" . $entity->getId() . "'";

        $orderQuery = "";
        if (!is_null($orderColumn)) {
            $orderQuery .= "ORDER BY $orderColumn ";
            if (!is_null($orderType)) {
                $orderQuery .= "$orderType";
            } else {
                $orderQuery .= "ASC";
            }
        }

        $query = $selectQuery . $joinQuery . $whereQuery . $orderQuery;
        $queryResult = $this->getDataSource()->query($query);
        if ($queryResult) {
            $collection = new Collection($relationMapper->getClass(), $queryResult, $relationMapper);
        } else {
            $collection = new Collection($relationMapper->getClass(), array(), $relationMapper);
        }

        return $collection;
    }
994955
protected function getJoinKeys(Relation $relation)
    {
        if ($relation instanceof MorphTo) {
            throw new LogicException("MorphTo relation cannot be joined.");
        }

        if ($relation instanceof HasOneOrMany) {
            return [$relation->getQualifiedForeignKeyName(), $relation->getQualifiedParentKeyName()];
        }

        if ($relation instanceof BelongsTo) {
            return [$relation->getQualifiedForeignKeyName(), $relation->getQualifiedOwnerKeyName()];
        }

        if ($relation instanceof BelongsToMany) {
            return [$relation->getQualifiedRelatedPivotKeyName(), $relation->getRelated()->getQualifiedKeyName()];
        }

        if ($relation instanceof HasManyThrough) {
            $fk = $relation->getQualifiedFarKeyName();

            return [$fk, $relation->getParent()->getQualifiedKeyName()];
        }
    }
892652
public function getCmsSpecialRelationTranslated($relation)
    {
        if (    ! array_key_exists($relation, $this->relationsConfig)
            ||  ! array_key_exists('translated', $this->relationsConfig[$relation])
        ) {
            return false;
        }

        return (bool) $this->relationsConfig[ $relation ]['translated'];
    }
1060616
protected function findRelationByName($relationName)
    {
        foreach ($this->relations as $relation) {
            if ($relation->name() == $relationName || $relation->entity() == $relationName) {
                return $relation;
            }
        }

        return null;
    }
894762
protected function nestedRelations( $relation )
	{
		$nested = [];

		// We are basically looking for any relationships that are nested deeper than
		// the given top-level relationship. We will just check for any relations
		// that start with the given top relations and adds them to our arrays.
		foreach ( $this->eagerLoad as $name => $constraints )
		{
			if ( $this->isNested( $name, $relation ) )
			{
				$nested[substr( $name, strlen( $relation . '.' ) )] = $constraints;
			}
		}

		return $nested;
	}