Automatically names and creates foreign key.
@param $table
@param $columns
@param $refTable
@param $refColumns
@return int
@throws \yii\db\Exception
186668
public static function dropForeignKey($table, $columns, $refTable, $refColumns)
    {
        $name = static::createForeignKeyName($table, $columns, $refTable);
        $fks = Yii::$app->db->schema->getTableSchema($table)->foreignKeys;
        $search = array_merge([$refTable], array_combine((array)$columns, (array)$refColumns));
        if (!in_array($search, $fks)) {
            return true;
        }
        return Yii::$app->db->createCommand()->dropForeignKey($name, $table)->execute();
    }
1254112
public function foreign(
        $table,
        $localColumnNames,
        $foreignColumnNames = 'id',
        $options = [],
        $constraintName = null
    ) {
        $localColumnNames   = is_array($localColumnNames) ? $localColumnNames : [$localColumnNames];
        $foreignColumnNames = is_array($foreignColumnNames) ? $foreignColumnNames : [$foreignColumnNames];

        return $this->table->addForeignKeyConstraint($table, $localColumnNames, $foreignColumnNames, $options,
            $constraintName);
    }
501713
private function updateTable(array $columns, Table &$table) {
        $this->updateReferences($table);
        $canUpdate = false;
        foreach ($columns['remove'] as $columnName) {
            $canUpdate = true;
            $table->dropColumn(Util::camelTo_($columnName));
        }

        foreach ($columns['update'] as $columnName => &$desc) {
            $canUpdate = true;
            $dbColumnName = Util::camelTo_($columnName);

            $this->checkIndexes($dbColumnName, $desc, $table);

            if (isset($desc['attrs']['reference'])) {
                $onDelete = (isset($desc['attrs']['reference']['onDelete'])) ?
                        $desc['attrs']['reference']['onDelete'] : 'RESTRICT';
                $onUpdate = (isset($desc['attrs']['reference']['onUpdate'])) ?
                        $desc['attrs']['reference']['onUpdate'] : 'RESTRICT';
                $table->alterReference($dbColumnName, $desc['attrs']['reference']['table'], $desc['attrs']['reference']['column'], $onDelete, $onUpdate);
                unset($desc['attrs']['reference']['table']);
                unset($desc['attrs']['reference']['column']);
                unset($desc['attrs']['reference']['model']);

                if (isset($desc['attrs']['reference']['onUpdate']))
                    unset($desc['attrs']['reference']['onUpdate']);
                if (isset($desc['attrs']['reference']['onDelete']))
                    unset($desc['attrs']['reference']['onDelete']);

                if (!empty($desc['attrs']['reference'])) {
                    $desc['attrs'] = array_merge($desc['attrs'], $desc['attrs']['reference']);
                    unset($desc['attrs']['reference']);
                }
            }

            $table->alterColumn($dbColumnName, $this->parseAttributes($columnName, $desc, false));

            if (isset($desc['attrs']['primary']) && $desc['attrs']['primary'])
                $table->setPrimaryKey($dbColumnName);
        }

        foreach ($columns['new'] as $columnName => $desc) {
            $canUpdate = true;
            $dbColumnName = Util::camelTo_($columnName);

            if (isset($desc['attrs']['reference'])) {
                $onDelete = (isset($desc['attrs']['reference']['onDelete'])) ?
                        $desc['attrs']['reference']['onDelete'] : 'RESTRICT';
                $onUpdate = (isset($desc['attrs']['reference']['onUpdate'])) ?
                        $desc['attrs']['reference']['onUpdate'] : 'RESTRICT';
                $table->addReference($dbColumnName, $desc['attrs']['reference']['table'], $desc['attrs']['reference']['column'], $onDelete, $onUpdate);
                unset($desc['attrs']['reference']['table']);
                unset($desc['attrs']['reference']['column']);
                unset($desc['attrs']['reference']['model']);

                if (isset($desc['attrs']['reference']['onUpdate']))
                    unset($desc['attrs']['reference']['onUpdate']);
                if (isset($desc['attrs']['reference']['onDelete']))
                    unset($desc['attrs']['reference']['onDelete']);

                if (!empty($desc['attrs']['reference'])) {
                    $desc['attrs'] = array_merge($desc['attrs'], $desc['attrs']['reference']);
                    unset($desc['attrs']['reference']);
                }
            }

            $table->addColumn($dbColumnName, $this->parseAttributes($columnName, $desc, false));

            $this->checkIndexes($dbColumnName, $desc, $table);

            if (isset($desc['attrs']['primary']) && $desc['attrs']['primary'])
                $table->setPrimaryKey($dbColumnName);
        }

        if ($canUpdate) {
            $droppedRefs = array();
            foreach ($table->getBackReferences() as $refArray) {
                foreach ($refArray as $ref) {
                    $refTable = new Table($ref['refTable'], $table->getConnection());
                    foreach ($refTable->getReferences() as $col => $array) {
                        if ($refTable->getName() !== $table->getName() && $array['refTable'] === $table->getName()) {
                            $refTable->dropReference($col);
                            $droppedRefs[$col][] = array_merge(array(
                                'table' => $refTable,
                                    ), $array);

                            $table->getConnection()->alterTable($refTable);
                        }
                    }
                }
            }
            $return = $table->getConnection()->alterTable($table);

            foreach ($droppedRefs as $col => $array) {
                foreach ($array as $ref) {
                    $onDelete = (!empty($ref['onDelete'])) ? $ref['onDelete'] : 'RESTRICT';
                    $onUpdate = (!empty($ref['onUpdate'])) ? $ref['onUpdate'] : 'RESTRICT';
                    $ref['table']->addReference($col, $ref['refTable'], $ref['refColumn'], $onDelete, $onUpdate);

                    $table->getConnection()->alterTable($ref['table']);
                }
            }
            if ($return) {
                $table->getConnection()->flush();
                return true;
            }
        }

        return false;
    }
190378
public static function field_exists($table, $columns, $db = null)
	{
		if ( ! is_array($columns))
		{
			$columns = array($columns);
		}

		try
		{
			\DB::select_array($columns)->from($table)->limit(1)->execute($db ? $db : static::$connection);
			return true;
		}
		catch (\Database_Exception $e)
		{
			// check if we have a DB connection at all
			$connection = \Database_Connection::instance($db ? $db : static::$connection)->has_connection();

			// if no connection could be made, re throw the exception
			if ( ! $connection)
			{
				throw $e;
			}

			return false;
		}
	}
523212
private function _createFkData($data, $table)
    {
        $name = $table . ucfirst(Text::singular($data['table'])) . 'Fk';
        $structure = [
            'constraintType' => 'FOREIGN KEY',
            'constraintName' => $name,
            'columnName' => $data['from'],
            'referenceTable' => $data['table'],
            'referenceColumn' => $data['to'],
            'onUpdate' => $data['on_update'],
            'onDelete' => $data['on_delete']
        ];
        return $structure;
    }
1257833
public function findForeignKey(string $column): ?AbstractForeignKey
    {
        foreach ($this->foreignKeys as $reference) {
            if ($reference->getColumn() == $column) {
                return $reference;
            }
        }

        return null;
    }
611638
protected function isPrimaryKey(Table $table, Column $column)
	{
		if ($table->hasPrimaryKey()) {
			$primaryKeys = $table->getPrimaryKey()->getColumns();

			return in_array($column->getName(), $primaryKeys);
		}

		return false;
	}
996321
public function from($table, $columns = null)
    {
        $this->table($table);
        if( !empty($columns) ) {
            $this->columns($columns);
        }
        return $this;
    }
1188426
protected function _foreignKeyAcceptsNull(Table $table, array $properties)
    {
        return !in_array(
            false,
            array_map(
                function ($prop) use ($table) {
                    return $table->getSchema()->isNullable($prop);
                },
                $properties
            )
        );
    }
420554
private function createTable(Table $table)
    {
        if ($this->getSqlStatements) {
            $createFlags = AbstractPlatform::CREATE_INDEXES |
                AbstractPlatform::CREATE_FOREIGNKEYS;
            $this->addSql(
                $this->getPlatform()
                    ->getCreateTableSQL($table, $createFlags)
            );
        } else {
            $this->schemaManager->createTable($table);
        }
    }
1342876
public function foreignKey(string $column): AbstractForeignKey
    {
        if (!$this->hasColumn($column)) {
            throw new SchemaException("Undefined column '{$column}' in '{$this->getName()}'");
        }

        if ($this->hasForeignKey($column)) {
            return $this->current->findForeignKey($column);
        }

        if ($this->initial->hasForeignKey($column)) {
            //Let's ensure that FK name is always stays synced (not regenerated)
            $name = $this->initial->findForeignKey($column)->getName();
        } else {
            $name = $this->createIdentifier('foreign', [$column]);
        }

        $foreign = $this->createForeign($name)->column($column);

        //Adding to current schema
        $this->current->registerForeignKey($foreign);

        //Let's ensure index existence to performance and compatibility reasons
        $this->index([$column]);

        return $foreign;
    }
74272
function addForeignKey($table, $pkname, $tables)
	{
		if ( is_string($tables) )
			$tables = array($tables);
			
		
		$this->_foreignKeys[$table] = array(
					'primaryKey' => $pkname,
					'tables' => $tables
				);
	}
644238
public function from($table, $columns = null) {
		$this->_criteria->setModelName($table);
		
		if ($columns !== null) {
			$this->_criteria->columns($columns);
		}
		
		return $this;
	}
288884
private function updateReferences(Table &$table) {
        $this->ignoreThis();
        foreach ($table->getBackReferences() as $array) {
            foreach ($array as $ref) {
                if (in_array($ref['refTable'], $this->getIgnore()))
                    continue;

                $refTable = new Table($ref['refTable'], $table->getConnection());
                $modelClass = self::getModelTable($ref['refTable']);
                if (!empty($modelClass)) {
                    $mapper = is_array($modelClass) ?
                            new $modelClass[count($modelClass) - 1] :
                            new $modelClass;
                    $mapper->setConnection($table->getConnection());
                    $mapper->init($refTable, $this->getIgnore());
                }
            }
        }
    }
942512
protected function getTableForeignKeys(): array
    {
        $data = [];

        $fks = $this->db->schema->getTableForeignKeys($this->tableName, true);

        /* @var $fk ForeignKeyConstraint */
        foreach ($fks as $fk) {
            $data[$fk->name] = new TableForeignKey([
                'name' => $fk->name,
                'columns' => $fk->columnNames,
                'refTable' => $fk->foreignTableName,
                'refColumns' => $fk->foreignColumnNames,
                'onDelete' => $fk->onDelete,
                'onUpdate' => $fk->onUpdate,
            ]);
        }

        return $data;
    }
485501
public function addReference($ruleKey, $columns, $refTableClass, $refColumns,
                                 $onDelete = null, $onUpdate = null)
    {
        $reference = array(self::COLUMNS         => (array) $columns,
                           self::REF_TABLE_CLASS => $refTableClass,
                           self::REF_COLUMNS     => (array) $refColumns);

        if (!empty($onDelete)) {
            $reference[self::ON_DELETE] = $onDelete;
        }

        if (!empty($onUpdate)) {
            $reference[self::ON_UPDATE] = $onUpdate;
        }

        $this->_referenceMap[$ruleKey] = $reference;

        return $this;
    }
1258657
protected function setColumnPropertiesFor($column)
    {
        $columnName = $column['name'];

        if ($column['searchable'] == 'true' && ! in_array($columnName, config('laratables.non_searchable_columns'))) {
            $this->searchColumns[] = $columnName;
        }

        if ($this->isCustomColumn($columnName) && ! isRelationColumn($columnName)) {
            return;
        }

        if (isRelationColumn($columnName)) {
            $this->relationshipsManager->addRelation($columnName);

            if ($foreignKeys = $this->relationshipsManager->getRelationSelectColumns($columnName)) {
                array_push($this->selectColumns, ...$foreignKeys);
            }

            return;
        }

        $this->selectColumns[] = $columnName;
    }