Creates a hasMany relation
@param $modelClass
@param $columnName
@param array $options
@return Relation
425734
public static function hasMany($modelClass, $columnName, $options = []) {
        $options['type'] = self::HAS_MANY;
        $options['modelClass'] = $modelClass;
        $options['compares'] = [["t.__PK__", (false === strpos($columnName, '.')) ? "r.$columnName" : $columnName, "="]];
        return new self($options);
    }
1207686
public function manyToOne ($relatedTable, $relatedKey = null, $key = null, $relationIdentifier = null)
		{
			if (is_null($relationIdentifier)) {
				$relationIdentifier = $relatedTable;
			}

			$this->relations[$relationIdentifier] = new ManyToOne(
				$this,
				$this->schema->getTable($relatedTable, true),
				$key,
				$relatedKey
			);

			return $this;
		}
58991
public static function manyToMany($modelClass, $connection, $options = []) {
        $options['type'] = self::MANY_TO_MANY;
        $options['modelClass'] = $modelClass;
        $connection = explode('(', $connection);
        $table = $connection[0];
        list($c1, $c2) = explode(',', $connection[1]);
        $r = new self($options);
        $c1 = trim($c1);
        $c2 = trim($c2);
        $r->join(trim($table), [["t.__PK__", "j.$c1", "="]])
            ->compare(["j.$c2" => "r." . $modelClass::getDb()->getTablePk($modelClass::getTableName())]);
        return $r;
    }
1263105
public function getColumnClassName($options)
	{
		$model = $this->config->getDataModel();
		$namespace = __NAMESPACE__ . '\\';

		//if the relationship is set
		if ($method = $this->validator->arrayGet($options, 'relationship'))
		{
			if (method_exists($model, $method))
			{
				$relationship = $model->{$method}();

				if (is_a($relationship, self::BELONGS_TO_MANY))
				{
					return $namespace . 'Relationships\BelongsToMany';
				}
				else if (is_a($relationship, self::HAS_ONE) || is_a($relationship, self::HAS_MANY))
				{
					return $namespace . 'Relationships\HasOneOrMany';
				}
			}

			//assume it's a nested relationship
			return $namespace . 'Relationships\BelongsTo';
		}

		return $namespace . 'Column';
	}
980580
public function changeColumn($columnName, $newColumnType, $options = [])
    {
        if (!$newColumnType instanceof Column) {
            $newColumn = new Column();
            $newColumn->setType($newColumnType);
            $newColumn->setOptions($options);
        } else {
            $newColumn = $newColumnType;
        }

        return parent::changeColumn($columnName, $newColumn);
    }
860107
public function createIndex($indexName, $columns, $condition = null, &$params = [], $options = [])
    {
        return $this->db->createIndex($this->name, $indexName, $columns, $condition, $params, $options);
    }
1094953
protected function createModelRelations($modelName, $groupDir, $groupNs)
    {
        $relationsName = $modelName;
        $relationsNs = $this->getConfig('relations_ns').$groupNs;
        $relationsPath = str_replace(
            ['/', '\\'],
            DIRECTORY_SEPARATOR,
            $this->getConfig('relations_dir')."$groupDir/$relationsName.php"
        );

        return new Relations($relationsName, $relationsNs, $relationsPath);
    }
235104
public static function getAllRelationshipsForModel($modelClassName)
    {
        $modelClassName = self::getModelClass($modelClassName);

        if (!isset(self::$relationshipCache[$modelClassName])) {
            $schemas = self::getAllSchemas();
            $relationships = [];

            foreach ($schemas as $schema) {
                if (isset($schema->relationships[$modelClassName])) {
                    $relationships = array_merge($relationships, $schema->relationships[$modelClassName]);
                }
            }

            self::$relationshipCache[$modelClassName] = $relationships;
        }

        return self::$relationshipCache[$modelClassName];
    }
141834
protected function relationColumn($related, $model, $column = null)
    {
        $table = $related::$table;
        //
        return !is_null($column) ? $column : $this->idKey($table);
    }
945540
public static function viaListFormat($model, $attribute, $options = [])
    {
        $relation = $model->getRelation($attribute);
        $relationClass = $relation->modelClass;
        $columns = Yii::$app->db->getTableSchema($relationClass::tableName())->columnNames;
        $titles = array_intersect(['title', 'name', 'username'], $columns);
        if (!$title = reset($titles)) {
            throw new \Exception(Yii::t('app', 'Relation does not have any title column'));
        }
        return array_merge([
            'attribute' => $attribute,
            'format' => 'raw',
            'value' => !$model->isNewRecord
                ? implode(', ', $relation->select($title)->column())
                : function ($data) use ($attribute, $title) {
                    return implode(', ', $data->getRelation($attribute)->select($title)->column());
                },
            'filter' => false,
            //'visible' => $model->isAttributeSafe($attribute),
        ], $options);
    }
455148
public function fetchColumn(QueryBuilder $builder, string $modelClass, string $columnName): iterable
    {
        $statement = $builder->execute();
        $statement->setFetchMode(PDOConnection::FETCH_ASSOC);

        if ($this->isFetchTyped() === true) {
            $platform = $builder->getConnection()->getDatabasePlatform();
            $typeName = $this->getModelSchemas()->getAttributeTypes($modelClass)[$columnName];
            $type     = Type::getType($typeName);
            while (($attributes = $statement->fetch()) !== false) {
                $value     = $attributes[$columnName];
                $converted = $type->convertToPHPValue($value, $platform);

                yield $converted;
            }
        } else {
            while (($attributes = $statement->fetch()) !== false) {
                $value = $attributes[$columnName];

                yield $value;
            }
        }

        $this->clearFetchParameters();
    }
998609
public function hasMany($hasMany, callable $callback = null, $alias = null)
    {
        return $this->returnRelation(HasMany::class, $hasMany, $callback, $alias);
    }
1327996
public function relation($relationName)
    {
        if (!$relation = $this->findRelationByName($relationName)) {
            throw new ModelException(sprintf('Unknown relation, relation "%s" not found in model "%s"', $relationName, $this->entity));
        }

        return $relation;
    }
667926
public function belongsTo($model, $options = array())
    {
        if (isset($this->_relationsCache[$model])) {
            return $this->_relationsCache[$model];
        }

        $options = static::getRelationInfo($model, $options);

        if (!isset($options['localKey'])) {
            $options['localKey'] = Inflector::foreignKey($model);
        }

        if (!isset($options['foreignKey'])) {
            $options['foreignKey'] = $options['model']::primaryKey();
        }

        return $this->_relationsCache[$model] = $options['model']::select()
            ->where("{$options['foreignKey']} = ?", $this->{$options['localKey']})
            ->fetch();
    }
1338542
protected static function _initRelationship($relationship, $options)
    {
        $classShortName = basename(str_replace('\\', '/', static::$rootClass));

        // apply defaults
        if (empty($options['type'])) {
            $options['type'] = 'one-one';
        }
        
        if ($options['type'] == 'one-one') {
            if (empty($options['local'])) {
                $options['local'] = $relationship . 'ID';
            }
                
            if (empty($options['foreign'])) {
                $options['foreign'] = 'ID';
            }
        } elseif ($options['type'] == 'one-many') {
            if (empty($options['local'])) {
                $options['local'] = 'ID';
            }
                    
            if (empty($options['foreign'])) {
                $options['foreign'] =  $classShortName. 'ID';
            }
                
            if (!isset($options['indexField'])) {
                $options['indexField'] = false;
            }
                
            if (!isset($options['conditions'])) {
                $options['conditions'] = [];
            } elseif (is_string($options['conditions'])) {
                $options['conditions'] = [$options['conditions']];
            }
                
            if (!isset($options['order'])) {
                $options['order'] = false;
            }
        } elseif ($options['type'] == 'context-children') {
            if (empty($options['local'])) {
                $options['local'] = 'ID';
            }
                    
            if (empty($options['contextClass'])) {
                $options['contextClass'] = get_called_class();
            }
                
            if (!isset($options['indexField'])) {
                $options['indexField'] = false;
            }
                
            if (!isset($options['conditions'])) {
                $options['conditions'] = [];
            }
                
            if (!isset($options['order'])) {
                $options['order'] = false;
            }
        } elseif ($options['type'] == 'context-parent') {
            if (empty($options['local'])) {
                $options['local'] = 'ContextID';
            }
                    
            if (empty($options['foreign'])) {
                $options['foreign'] = 'ID';
            }

            if (empty($options['classField'])) {
                $options['classField'] = 'ContextClass';
            }

            if (empty($options['allowedClasses'])) {
                $options['allowedClasses'] = static::$contextClasses;
            }
        } elseif ($options['type'] == 'many-many') {
            if (empty($options['class'])) {
                throw new Exception('Relationship type many-many option requires a class setting.');
            }
        
            if (empty($options['linkClass'])) {
                throw new Exception('Relationship type many-many option requires a linkClass setting.');
            }
                
            if (empty($options['linkLocal'])) {
                $options['linkLocal'] = $classShortName . 'ID';
            }
        
            if (empty($options['linkForeign'])) {
                $foreignShortname = basename(str_replace('\\', '/', $options['class']::$rootClass));
                $options['linkForeign'] =  $foreignShortname . 'ID';
            }
        
            if (empty($options['local'])) {
                $options['local'] = 'ID';
            }

            if (empty($options['foreign'])) {
                $options['foreign'] = 'ID';
            }

            if (!isset($options['indexField'])) {
                $options['indexField'] = false;
            }
                
            if (!isset($options['conditions'])) {
                $options['conditions'] = [];
            }
                
            if (!isset($options['order'])) {
                $options['order'] = false;
            }
        }
           
        if (static::isVersioned() && $options['type'] == 'history') {
            if (empty($options['class'])) {
                $options['class'] = get_called_class();
            }
        }
                
        return $options;
    }
82910
public function hasMany($modelName, $foreignKey=null, $localKey=null)
    {
        return $this->_relationship($modelName, __FUNCTION__, $foreignKey, $localKey);
    }
1288688
public function changeColumn($columnName, $newColumnType, $options = [])
    {
        // create a column object if one wasn't supplied
        if (!$newColumnType instanceof Column) {
            $newColumn = new Column();
            $newColumn->setType($newColumnType);
            $newColumn->setOptions($options);
        } else {
            $newColumn = $newColumnType;
        }

        // if the name was omitted use the existing column name
        if (null === $newColumn->getName() || strlen($newColumn->getName()) === 0) {
            $newColumn->setName($columnName);
        }

        $this->getAdapter()->changeColumn($this->getName(), $columnName, $newColumn);

        return $this;
    }