Skip to content

[11.x] Add ability to handle optional Incremental IDs $table->id()->onlyWhenEnforced() #49460

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

Closed
wants to merge 10 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
49 changes: 37 additions & 12 deletions src/Illuminate/Database/Schema/Blueprint.php
Original file line number Diff line number Diff line change
Expand Up @@ -688,7 +688,7 @@ public function foreign($columns, $name = null)
* Create a new auto-incrementing big integer (8-byte) column on the table.
*
* @param string $column
* @return \Illuminate\Database\Schema\ColumnDefinition
* @return \Illuminate\Database\Schema\IdColumnDefinition
*/
public function id($column = 'id')
{
Expand All @@ -699,22 +699,27 @@ public function id($column = 'id')
* Create a new auto-incrementing integer (4-byte) column on the table.
*
* @param string $column
* @return \Illuminate\Database\Schema\ColumnDefinition
* @return \Illuminate\Database\Schema\IdColumnDefinition
*/
public function increments($column)
{
return $this->unsignedInteger($column, true);
return $this->integerIncrements($column);
}

/**
* Create a new auto-incrementing integer (4-byte) column on the table.
*
* @param string $column
* @return \Illuminate\Database\Schema\ColumnDefinition
* @return \Illuminate\Database\Schema\IdColumnDefinition
*/
public function integerIncrements($column)
{
return $this->unsignedInteger($column, true);
return $this->addColumnDefinition(new IdColumnDefinition([
'type' => 'integer',
'name' => $column,
'autoIncrement' => true,
'unsigned' => true,
]));
}

/**
Expand All @@ -725,40 +730,60 @@ public function integerIncrements($column)
*/
public function tinyIncrements($column)
{
return $this->unsignedTinyInteger($column, true);
return $this->addColumnDefinition(new IdColumnDefinition([
'type' => 'tinyInteger',
'name' => $column,
'autoIncrement' => true,
'unsigned' => true,
]));
}

/**
* Create a new auto-incrementing small integer (2-byte) column on the table.
*
* @param string $column
* @return \Illuminate\Database\Schema\ColumnDefinition
* @return \Illuminate\Database\Schema\IdColumnDefinition
*/
public function smallIncrements($column)
{
return $this->unsignedSmallInteger($column, true);
return $this->addColumnDefinition(new IdColumnDefinition([
'type' => 'smallInteger',
'name' => $column,
'autoIncrement' => true,
'unsigned' => true,
]));
}

/**
* Create a new auto-incrementing medium integer (3-byte) column on the table.
*
* @param string $column
* @return \Illuminate\Database\Schema\ColumnDefinition
* @return \Illuminate\Database\Schema\IdColumnDefinition
*/
public function mediumIncrements($column)
{
return $this->unsignedMediumInteger($column, true);
return $this->addColumnDefinition(new IdColumnDefinition([
'type' => 'mediumInteger',
'name' => $column,
'autoIncrement' => true,
'unsigned' => true,
]));
}

/**
* Create a new auto-incrementing big integer (8-byte) column on the table.
*
* @param string $column
* @return \Illuminate\Database\Schema\ColumnDefinition
* @return \Illuminate\Database\Schema\IdColumnDefinition
*/
public function bigIncrements($column)
{
return $this->unsignedBigInteger($column, true);
return $this->addColumnDefinition(new IdColumnDefinition([
'type' => 'bigInteger',
'name' => $column,
'autoIncrement' => true,
'unsigned' => true,
]));
}

/**
Expand Down
27 changes: 27 additions & 0 deletions src/Illuminate/Database/Schema/Builder.php
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,13 @@ class Builder
*/
public static $defaultMorphKeyType = 'int';

/**
* Indicates whether incremental primary key is required.
*
* @var string
*/
public static $enforceIncrementalPrimaryKey = false;

/**
* Indicates whether Doctrine DBAL usage will be prevented if possible when dropping, renaming, and modifying columns.
*
Expand Down Expand Up @@ -112,6 +119,26 @@ public static function morphUsingUlids()
return static::defaultMorphKeyType('ulid');
}

/**
* Set the default to enforce primary key.
*
* @return void
*/
public static function enforcePrimaryKey()
{
static::$enforceIncrementalPrimaryKey = true;
}

/**
* Set the default to not enforce primary key.
*
* @return void
*/
public static function optionalPrimaryKey()
{
static::$enforceIncrementalPrimaryKey = false;
}

/**
* Attempt to use native schema operations for dropping, renaming, and modifying columns, even if Doctrine DBAL is installed.
*
Expand Down
7 changes: 6 additions & 1 deletion src/Illuminate/Database/Schema/ColumnDefinition.php
Original file line number Diff line number Diff line change
Expand Up @@ -34,5 +34,10 @@
*/
class ColumnDefinition extends Fluent
{
//
/**
* Determine if column should be skipped.
*
* @var bool
*/
public $shouldBeSkipped = false;
}
4 changes: 4 additions & 0 deletions src/Illuminate/Database/Schema/Grammars/Grammar.php
Original file line number Diff line number Diff line change
Expand Up @@ -173,6 +173,10 @@ protected function getColumns(Blueprint $blueprint)
$columns = [];

foreach ($blueprint->getAddedColumns() as $column) {
if ($column->shouldBeSkipped) {
continue;
}

// Each of the column types has their own compiler functions, which are tasked
// with turning the column definition into its SQL format for this platform
// used by the connection. The column's modifiers are compiled and added.
Expand Down
20 changes: 20 additions & 0 deletions src/Illuminate/Database/Schema/IdColumnDefinition.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
<?php

namespace Illuminate\Database\Schema;

class IdColumnDefinition extends ColumnDefinition
{
/**
* Set the column to be added if enforced.
*
* @return $this
*/
public function onlyWhenEnforced()
{
if (Builder::$enforceIncrementalPrimaryKey === false) {
$this->shouldBeSkipped = true;
}

return $this;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ return new class extends Migration
public function up(): void
{
Schema::create('notifications', function (Blueprint $table) {
$table->id('uid')->onlyWhenEnforced();
$table->uuid('id')->primary();
$table->string('type');
$table->morphs('notifiable');
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
<?php

namespace Illuminate\Tests\Integration\Database;

use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Schema\Builder;
use Illuminate\Support\Facades\Schema;
use Orchestra\Testbench\TestCase;

class DatabaseSchemaEnforceIncrementalPrimaryKeyTest extends TestCase
{
public function testMigrationsTableHasPrimaryKey()
{
Builder::enforcePrimaryKey();

Schema::create('table_with_required_id', function (Blueprint $table) {
$table->id()->onlyWhenEnforced();
$table->uuid();
$table->text('name');
});

Builder::optionalPrimaryKey();

Schema::create('table_with_optional_id', function (Blueprint $table) {
$table->id()->onlyWhenEnforced();
$table->uuid();
$table->text('name');
});

$this->assertSame([
'id',
'uuid',
'name',
], collect(Schema::getColumns('table_with_required_id'))->pluck('name')->all());

$this->assertSame([
'uuid',
'name',
], collect(Schema::getColumns('table_with_optional_id'))->pluck('name')->all());
}
}