@param string      $relation
@param string|null $joinColumn
@param string|null $referenceColumn
@param bool|false  $nullable
@param bool|false  $unique
@param string|null $onDelete
@param string|null $columnDefinition

@return $this
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;
    }
185392
public function property(string $memberExpression) : ColumnMappingDefiner
    {
        $this->memberParser->parse($this->class, $memberExpression);

        return new ColumnMappingDefiner(
            function (IColumn $column) use ($memberExpression) {
                $this->column($column);
                $this->propertyComponentIdMap[$memberExpression] = $column->getComponentId();
            },
            function ($componentId) use ($memberExpression) {
                $this->propertyComponentIdMap[$memberExpression] = $componentId;
            }
        );
    }
390533
private function isRelationForeignKeyNullable(Relation $relation)
    {
        $reflectionObj = new \ReflectionObject($relation);
        if (!$reflectionObj->hasProperty('foreignKey')) {
            return false;
        }
        $fkProp = $reflectionObj->getProperty('foreignKey');
        $fkProp->setAccessible(true);

        return isset($this->nullableColumns[$fkProp->getValue($relation)]);
    }
1111105
public function whereHas($relation)
    {
        if ( ! is_array($relation)) {
            $relation = func_get_args();
        }

        $this->whereHas[] = $relation;

        return $this;
    }
557782
public function withParentIdAs(string $columnName)
    {
        call_user_func($this->callback, function ($idString, Table $parentTable) use ($columnName) {
            /** @var IEntityMapper $mapper */
            $mapper = call_user_func($this->mapperLoader);
            $mapper->addForeignKey(ForeignKey::createWithNamingConvention(
                $mapper->getPrimaryTableName(),
                [$columnName],
                $parentTable->getName(),
                [$parentTable->getPrimaryKeyColumnName()],
                $this->identifying
                    ? ForeignKeyMode::CASCADE
                    : ForeignKeyMode::SET_NULL,
                ForeignKeyMode::CASCADE
            ));

            if ($this->orderPersistColumn) {
                $persistHook = new OrderIndexPropertyLoaderHook(
                    $mapper->getObjectType(),
                    $mapper->getPrimaryTable(),
                    $this->orderPersistColumn,
                    $columnName,
                    $mapper->getDefinition()->getPropertyLinkedToColumn($this->orderPersistColumn)
                );

                $mapper->addPersistHook($persistHook);
                $persistHookId = $persistHook->getIdString();
            } else {
                $persistHookId = null;
            }

            return new ToManyRelation(
                $idString,
                $this->loadIds
                    ? new ToManyRelationIdentityReference($mapper, $this->bidirectionalRelationProperty)
                    : new ToManyRelationObjectReference($mapper, $this->bidirectionalRelationProperty, $persistHookId),
                $columnName,
                $this->identifying
                    ? new IdentifyingRelationMode()
                    : new NonIdentifyingRelationMode(),
                $this->orderByColumnNameDirectionMap,
                $this->orderPersistColumn
            );
        });
    }
1306045
public function mergeModelDefinedRelationConstraints( Builder $relation )
	{
		$removedScopes = $relation->removedScopes();

		$relationQuery = $relation->getQuery();

		// Here we have some relation query and the original relation. We need to copy over any
		// where clauses that the developer may have put in the relation definition function.
		// We need to remove any global scopes that the developer already removed as well.
		return $this->withoutGlobalScopes( $removedScopes )->mergeWheres( $relationQuery->wheres, $relationQuery->getBindings() );
	}
425052
protected function joinHasOneOrMany(HasOneOrMany $relation)
    {
        return $this->instance->join(
            $relation->getRelated()->getTable(),
            $relation->getRelated()->getTable() . '.' . $relation->getParent()->getForeignKey(),
            '=',
            $relation->getParent()->getTable() . '.' . $relation->getParent()->getKeyName()
        );
    }
901785
public function addCloneableRelation($relation) {
		$relations = $this->getCloneableRelations();
		if (in_array($relation, $relations)) return;
		$relations[] = $relation;
		$this->cloneable_relations = $relations;
	}
1044768
public function addReference($columnName, $refTable, $refColumn,
            $onDelete = 'RESTRICT', $onUpdate = 'RESTRICT') {
        $this->addIndex($columnName);
        $this->newReferences[$columnName] = array(
            'table' => $refTable,
            'column' => $refColumn,
            'onDelete' => $onDelete,
            'onUpdate' => $onUpdate,
        );
        return $this;
    }
412190
public function setListParent($relation, $recordKey = null)
    {
        if (false !== $relation && empty($relation)) {
            return $this->clearListParent();
        }

        if (false === $relation) {
            session()->put($this->getSessionKey(static::TYPE_PARENT), static::PARENT_DISABLE);
        } else {
            session()->put($this->getSessionKey(static::TYPE_PARENT), $relation . ':' . $recordKey);
        }

        return $this;
    }
1113277
public function related($relation, $column, $operator = null, $value = null, $boolean = 'and')
    {
        if ($column instanceof \Closure) {
            return $this->addRelated($relation, $column);
        }

        // If there is no value it is a where = ? query and we set the appropriate params
        if ($value === null) {
            $value = $operator;
            $operator = '=';
        }

        return $this->addRelated($relation, function ($query) use ($column, $operator, $value, $boolean) {
            return $query->where($column, $operator, $value, $boolean);
        });
    }
1208454
protected function generateJoinColumnAnnotation(array $joinColumn)
    {
        $joinColumnAnnot = array();

        if (isset($joinColumn['name'])) {
            $joinColumnAnnot[] = 'name="' . $joinColumn['name'] . '"';
        }

        if (isset($joinColumn['referencedColumnName'])) {
            $joinColumnAnnot[] = 'referencedColumnName="' . $joinColumn['referencedColumnName'] . '"';
        }

        if (isset($joinColumn['unique']) && $joinColumn['unique']) {
            $joinColumnAnnot[] = 'unique=' . ($joinColumn['unique'] ? 'true' : 'false');
        }

        if (isset($joinColumn['nullable'])) {
            $joinColumnAnnot[] = 'nullable=' . ($joinColumn['nullable'] ? 'true' : 'false');
        }

        if (isset($joinColumn['onDelete'])) {
            $joinColumnAnnot[] = 'onDelete="' . ($joinColumn['onDelete'] . '"');
        }

        if (isset($joinColumn['columnDefinition'])) {
            $joinColumnAnnot[] = 'columnDefinition="' . $joinColumn['columnDefinition'] . '"';
        }

        return '@' . $this->annotationsPrefix . 'JoinColumn(' . implode(', ', $joinColumnAnnot) . ')';
    }
829526
public function addJoinColumn($columnName, $referencedColumnName, $nullable = true, $unique = false, $onDelete = null, $columnDef = null)
    {
        $this->joinColumns[] = array(
            'name' => $columnName,
            'referencedColumnName' => $referencedColumnName,
            'nullable' => $nullable,
            'unique' => $unique,
            'onDelete' => $onDelete,
            'columnDefinition' => $columnDef,
        );
        return $this;
    }
1008598
public function addRelationSelectColumns($relation)
    {
        $join = $this->joins[$relation];
        call_user_func(array($join->getTableMap()->getPeerClassname(), 'addSelectColumns'), $this, $join->getRelationAlias());

        return $this;
    }
65331
public function orderByAsc(string $columnName) : OneToManyRelationDefiner
    {
        $this->orderByColumnNameDirectionMap[$columnName] = Ordering::ASC;

        return $this;
    }
1265109
public function join($table, $on = null, $where = null, $binds = [], $type = 'LEFT')
    {
        if ($table instanceof Relation) {
            if (is_only_callable($on)) {
                /**
                 * Is this needed?
                 */
                Reflect::call($on, [$table, $table->getQuery()]);
            }

            $table->mergeToQuery($this->getQuery());
        } elseif ($table instanceof Entity) {
            $query = $table->getQuery();

            $sql = $query->buildSQL();

            $this->getQuery()->join(
                $type . ' JOIN (' . $sql . ') AS `' . $where . '` ON (' .
                (strpos($on, '(') ? '' : ($where . '.')) . $on . ')',
                null,
                null,
                $query->buildBinds()
            );
        } else {
            $this->getQuery()->join($table, $on, $where, $binds);
        }

        return $this;
    }
74181
public function getRelation(string $relation) : Relationship
    {
        // We want to run a relationship query without any constrains so that we will
        // not have to remove these where clauses manually which gets really hacky
        // and is error prone while we remove the developer's own where clauses.
        $query = Relationship::noConstraints(function () use ($relation) {
            return $this->entityMap->$relation($this->mapper->newInstance());
        });

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

        // If there are nested relationships set on the query, we will put those onto
        // the query instances so that they can be handled after this relationship
        // is loaded. In this way they will all trickle down as they are loaded.
        if (count($nested) > 0) {
            $query->getQuery()->with($nested);
        }

        return $query;
    }