Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[11.x] Enhance database migrations #51373

Open
wants to merge 14 commits into
base: 11.x
Choose a base branch
from
103 changes: 95 additions & 8 deletions src/Illuminate/Database/Schema/Blueprint.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
use Illuminate\Database\Query\Expression;
use Illuminate\Database\Schema\Grammars\Grammar;
use Illuminate\Database\Schema\Grammars\MySqlGrammar;
use Illuminate\Database\Schema\Grammars\SQLiteGrammar;
use Illuminate\Support\Fluent;
use Illuminate\Support\Traits\Macroable;

Expand Down Expand Up @@ -78,6 +79,13 @@ class Blueprint
*/
public $after;

/**
* The blueprint state instance.
*
* @var \Illuminate\Database\Schema\BlueprintState|null
*/
private $state;

/**
* Create a new schema blueprint.
*
Expand Down Expand Up @@ -136,6 +144,10 @@ public function toSql(Connection $connection, Grammar $grammar)
$method = 'compile'.ucfirst($command->name);

if (method_exists($grammar, $method) || $grammar::hasMacro($method)) {
if ($this->hasState()) {
$this->state->update($command);
}

if (! is_null($sql = $grammar->$method($this, $command, $connection))) {
$statements = array_merge($statements, (array) $sql);
}
Expand All @@ -161,6 +173,8 @@ protected function ensureCommandsAreValid(Connection $connection)
/**
* Get all of the commands matching the given names.
*
* @deprecated Will be removed in a future Laravel version.
*
* @param array $names
* @return \Illuminate\Support\Collection
*/
Expand All @@ -180,17 +194,20 @@ protected function commandsNamed(array $names)
*/
protected function addImpliedCommands(Connection $connection, Grammar $grammar)
{
if (count($this->getAddedColumns()) > 0 && ! $this->creating()) {
array_unshift($this->commands, $this->createCommand('add'));
}

if (count($this->getChangedColumns()) > 0 && ! $this->creating()) {
array_unshift($this->commands, $this->createCommand('change'));
}

$this->addFluentIndexes($connection, $grammar);

$this->addFluentCommands($connection, $grammar);

if (! $this->creating()) {
$this->commands = array_map(
fn ($command) => $command instanceof ColumnDefinition
? $this->createCommand($command->change ? 'change' : 'add', ['column' => $command])
: $command,
$this->commands
);

$this->addAlterCommands($connection, $grammar);
}
}

/**
Expand Down Expand Up @@ -260,6 +277,45 @@ public function addFluentCommands(Connection $connection, Grammar $grammar)
}
}

/**
* Add the alter commands if whenever needed.
*
* @param \Illuminate\Database\Connection $connection
* @param \Illuminate\Database\Schema\Grammars\Grammar $grammar
* @return void
*/
public function addAlterCommands(Connection $connection, Grammar $grammar)
{
if ($grammar instanceof SQLiteGrammar) {
$alterCommands = $grammar->getAlterCommands($connection);
$commands = [];
$lastCommandWasAlter = false;
$hasAlterCommand = false;

foreach ($this->commands as $command) {
if (in_array($command->name, $alterCommands)) {
$lastCommandWasAlter = true;
$hasAlterCommand = true;
} elseif ($lastCommandWasAlter) {
$commands[] = $this->createCommand('alter');
$lastCommandWasAlter = false;
}

$commands[] = $command;
}

if ($lastCommandWasAlter) {
$commands[] = $this->createCommand('alter');
}

if ($hasAlterCommand) {
$this->state = new BlueprintState($this, $connection, $grammar);
}

$this->commands = $commands;
}
}

/**
* Determine if the blueprint has a create command.
*
Expand Down Expand Up @@ -1634,6 +1690,10 @@ protected function addColumnDefinition($definition)
{
$this->columns[] = $definition;

if (! $this->creating()) {
$this->commands[] = $definition;
}

if ($this->after) {
$definition->after($this->after);

Expand Down Expand Up @@ -1671,6 +1731,10 @@ public function removeColumn($name)
return $c['name'] != $name;
}));

$this->commands = array_values(array_filter($this->commands, function ($c) use ($name) {
hafezdivandari marked this conversation as resolved.
Show resolved Hide resolved
return ! $c instanceof ColumnDefinition || $c['name'] != $name;
}));

return $this;
}

Expand Down Expand Up @@ -1740,6 +1804,27 @@ public function getCommands()
return $this->commands;
}

/**
* Get the state of the blueprint.
*
* @return \Illuminate\Database\Schema\BlueprintState
*/
public function getState()
{
return $this->state;
}

/*
* Determine if the blueprint has state.
*
* @param mixed $name
* @return bool
*/
private function hasState(): bool
{
return ! is_null($this->state);
hafezdivandari marked this conversation as resolved.
Show resolved Hide resolved
}

/**
* Get the columns on the blueprint that should be added.
*
Expand All @@ -1755,6 +1840,8 @@ public function getAddedColumns()
/**
* Get the columns on the blueprint that should be changed.
*
* @deprecated Will be removed in a future Laravel version.
*
* @return \Illuminate\Database\Schema\ColumnDefinition[]
*/
public function getChangedColumns()
Expand Down
Loading