Skip to content

Commit fcb2cfe

Browse files
author
Nathan Esayeas
authored
Support for cascade, set null, restrict, and no action for onDelete actions (#230)
1 parent cf74a7a commit fcb2cfe

File tree

6 files changed

+48
-7
lines changed

6 files changed

+48
-7
lines changed

config/blueprint.php

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -94,4 +94,24 @@
9494
*/
9595

9696
'use_guarded' => false,
97+
98+
/*
99+
|--------------------------------------------------------------------------
100+
| Foreign Key ON DELETE action
101+
|--------------------------------------------------------------------------
102+
|
103+
| By default, Blueprint will set the `ON DELETE` action to 'cascade'.
104+
|
105+
| restrict / no action:
106+
| - No action is performed with the child data when the parent data is deleted.
107+
| cascade:
108+
| - The child data is either deleted when the parent data is deleted.
109+
| set null:
110+
| - The child data is set to NULL when the parent data is deleted.
111+
|
112+
| Supported: 'cascade', 'set_null', 'restrict', 'no_action'
113+
|
114+
*/
115+
116+
'on_delete' => 'cascade',
97117
];

src/Generators/MigrationGenerator.php

Lines changed: 21 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,13 @@ class MigrationGenerator implements Generator
1717
'uuidMorphs',
1818
];
1919

20+
const ON_DELETE_CLAUSES = [
21+
'cascade' => "->onDelete('cascade')",
22+
'restrict' => "->onDelete('restrict')",
23+
'set_null' => "->onDelete('set null')",
24+
'no_action' => "->onDelete('no action')",
25+
];
26+
2027
const UNSIGNABLE_TYPES = [
2128
'bigInteger',
2229
'decimal',
@@ -148,7 +155,9 @@ protected function buildDefinition(Model $model)
148155

149156
// TODO: unset the proper modifier
150157
$modifiers = collect($modifiers)->reject(function ($modifier) {
151-
return ((is_array($modifier) && key($modifier) === 'foreign')
158+
return (
159+
(is_array($modifier) && key($modifier) === 'foreign')
160+
|| (is_array($modifier) && key($modifier) === 'onDelete')
152161
|| $modifier === 'foreign'
153162
|| ($modifier === 'nullable' && $this->isLaravel7orNewer()));
154163
});
@@ -231,22 +240,29 @@ protected function buildForeignKey(string $column_name, ?string $on, string $typ
231240
$table = Str::lower(Str::plural($attributes[0]));
232241
}
233242

243+
$on_delete_clause = config('blueprint.on_delete', 'cascade');
244+
245+
$on_delete_suffix = self::ON_DELETE_CLAUSES[$on_delete_clause];
246+
234247
if ($this->isLaravel7orNewer() && $type === 'id') {
235248
$prefix = in_array('nullable', $modifiers)
236249
? '$table->foreignId' . "('{$column_name}')->nullable()"
237250
: '$table->foreignId' . "('{$column_name}')";
238251

252+
if ($on_delete_clause === 'cascade') {
253+
$on_delete_suffix = '->cascadeOnDelete()';
254+
}
239255
if ($column_name === Str::singular($table) . '_' . $column) {
240-
return self::INDENT . "{$prefix}->constrained()->cascadeOnDelete()";
256+
return self::INDENT . "{$prefix}->constrained(){$on_delete_suffix}";
241257
}
242258
if ($column === 'id') {
243-
return self::INDENT . "{$prefix}->constrained('{$table}')->cascadeOnDelete()";
259+
return self::INDENT . "{$prefix}->constrained('{$table}'){$on_delete_suffix}";
244260
}
245261

246-
return self::INDENT . "{$prefix}->constrained('{$table}', '{$column}')->cascadeOnDelete()";
262+
return self::INDENT . "{$prefix}->constrained('{$table}', '{$column}'){$on_delete_suffix}";
247263
}
248264

249-
return self::INDENT . '$table->foreign' . "('{$column_name}')->references('{$column}')->on('{$table}')->onDelete('cascade')";
265+
return self::INDENT . '$table->foreign' . "('{$column_name}')->references('{$column}')->on('{$table}'){$on_delete_suffix}";
250266
}
251267

252268
protected function getClassName(Model $model)

src/Lexers/ModelLexer.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,7 @@ class ModelLexer implements Lexer
9494
'index' => 'index',
9595
'primary' => 'primary',
9696
'foreign' => 'foreign',
97+
'ondelete' => 'onDelete',
9798
];
9899

99100
public function analyze(array $tokens): array

tests/Feature/Generator/MigrationGeneratorTest.php

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -395,6 +395,8 @@ public function output_does_not_duplicate_pivot_table_migration_laravel6()
395395
*/
396396
public function output_creates_foreign_keys_with_nullable_chained_correctly()
397397
{
398+
$this->app->config->set('blueprint.on_delete', 'set_null');
399+
398400
$this->files->expects('stub')
399401
->with('migration.stub')
400402
->andReturn(file_get_contents('stubs/migration.stub'));
@@ -419,6 +421,8 @@ public function output_creates_foreign_keys_with_nullable_chained_correctly()
419421
*/
420422
public function output_creates_foreign_keys_with_nullable_chained_correctly_laravel6()
421423
{
424+
$this->app->config->set('blueprint.on_delete', 'set_null');
425+
422426
$app = \Mockery::mock();
423427
$app->shouldReceive('version')
424428
->withNoArgs()

tests/fixtures/migrations/nullable-chaining-laravel6.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ public function up()
1717
$table->bigIncrements('id');
1818
$table->string('name');
1919
$table->unsignedBigInteger('user_id')->nullable();
20-
$table->foreign('user_id')->references('id')->on('users')->onDelete('cascade');
20+
$table->foreign('user_id')->references('id')->on('users')->onDelete('set null');
2121
$table->timestamps();
2222
});
2323
}

tests/fixtures/migrations/nullable-chaining.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ public function up()
1616
Schema::create('carts', function (Blueprint $table) {
1717
$table->id();
1818
$table->string('name');
19-
$table->foreignId('user_id')->nullable()->constrained()->cascadeOnDelete();
19+
$table->foreignId('user_id')->nullable()->constrained()->onDelete('set null');
2020
$table->timestamps();
2121
});
2222
}

0 commit comments

Comments
 (0)