Метод cascadeOnUpdate
Метод cascadeOnUpdate применяется к определению внешнего ключа в миграциях Laravel. Он указывает базе данных автоматически обновлять значение внешнего ключа в дочерней таблице при изменении значения первичного ключа в родительской таблице. Это обеспечивает целостность ссылочных данных и избавляет разработчика от необходимости вручную обрабатывать обновления связанных записей.
Синтаксис
<?php
Schema::table('child_table', function (Blueprint $table) {
$table->foreignId('parent_id')
->constrained('parent_table')
->cascadeOnUpdate();
});
?>
Метод вызывается цепочкой после определения внешнего ключа и не принимает параметров. Он добавляет условие ON UPDATE CASCADE к ограничению внешнего ключа.
Пример
Создадим миграцию для таблицы posts с внешним ключом на таблицу users. При обновлении идентификатора пользователя все связанные посты автоматически обновят свой внешний ключ:
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
public function up(): void
{
Schema::create('posts', function (Blueprint $table) {
$table->id();
$table->foreignId('user_id')
->constrained('users')
->cascadeOnUpdate();
$table->string('title');
$table->text('content');
$table->timestamps();
});
}
public function down(): void
{
Schema::dropIfExists('posts');
}
};
?>
В результате выполнения миграции создастся SQL-запрос с конструкцией:
ALTER TABLE posts
ADD CONSTRAINT posts_user_id_foreign
FOREIGN KEY (user_id) REFERENCES users(id)
ON UPDATE CASCADE
Пример
Теперь рассмотрим, как работает каскадное обновление на практике. Предположим, у нас есть таблицы users и posts, связанные внешним ключом с каскадным обновлением. Обновим идентификатор пользователя и проверим, что посты обновились автоматически:
<?php
namespace App\Http\Controllers;
use App\Models\User;
use App\Models\Post;
class UserController extends Controller
{
public function updateUser()
{
$user = User::find(1);
$oldId = $user->id;
$res = Post::where('user_id', $oldId)->get();
foreach ($res as $post) {
echo "Post ID: " . $post->id;
echo " User ID: " . $post->user_id . "\n";
}
echo "Update user id...\n";
User::where('id', $oldId)->update(['id' => 100]);
$res = Post::where('user_id', 100)->get();
foreach ($res as $post) {
echo "Post ID: " . $post->id;
echo " User ID: " . $post->user_id . "\n";
}
}
}
?>
Результат выполнения кода:
"Post ID: 1 User ID: 1"
"Post ID: 2 User ID: 1"
"Post ID: 3 User ID: 1"
"Update user id..."
"Post ID: 1 User ID: 100"
"Post ID: 2 User ID: 100"
"Post ID: 3 User ID: 100"
Как видно, после обновления идентификатора пользователя все связанные посты автоматически получили новое значение user_id. Это произошло на уровне базы данных без выполнения дополнительных запросов из приложения.
Пример
Метод cascadeOnUpdate также можно использовать при изменении существующей таблицы через метод table. Добавим внешний ключ с каскадным обновлением к уже существующей таблице comments:
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
public function up(): void
{
Schema::table('comments', function (Blueprint $table) {
$table->foreignId('post_id')
->constrained('posts')
->cascadeOnUpdate()
->cascadeOnDelete();
});
}
public function down(): void
{
Schema::table('comments', function (Blueprint $table) {
$table->dropForeign(['post_id']);
$table->dropColumn('post_id');
});
}
};
?>
В этом примере мы добавили внешний ключ с каскадным обновлением и удалением. Теперь при изменении id поста все связанные комментарии обновятся автоматически, а при удалении поста комментарии также будут удалены.
Смотрите также
-
метод
cascadeOnDelete,
который каскадно удаляет связанные записи -
метод
nullOnDelete,
который устанавливает NULL внешнему ключу при удалении -
метод
constrained,
который упрощает определение внешних ключей -
метод
foreign,
который создаёт внешний ключ