Удаление строк с помощью красноречивых отношений

#php #laravel

#php #laravel

Вопрос:

У меня есть таблицы «проекты» и «задачи». Каждый проект может иметь несколько задач, поэтому его отношение «один ко многим».

Каскад OnDelete не работает для меня

Когда я удаляю проект, а затем отправляю задачи, я получаю сообщение об ошибке. Поэтому мне нужно, чтобы при удалении проекта он удалял все связанные с этим задачи. Это мои миграции;

  Schema::create('tasks', function (Blueprint $table) {

            $table->increments('task_id')->default($value=null)->unsigned();

            $table->integer('proj_id')->nullable()->default($value=null)->foreign('proj_id')->references('proj_id')->on('projects')->onDelete('cascade');

 
 public function up()
    {
        Schema::create('projects', function (Blueprint $table) {

            $table->increments('proj_id')->nullable()->default($value=null)->foreign('proj_id')->references('proj_id')->on('tasks')->onDelete('cascade');

 

И это мои модели;

 class Project extends Model
{
    protected $primaryKey = 'proj_id';
    protected $fillable = ['proj_title','proj_desc','client_id','created_by'];



    public function client (){
        return $this->belongsTo('AppClient');
    }
    public function task (){
        return $this->hasMany('AppTask');
    }
 
 <?php

namespace App;

use IlluminateDatabaseEloquentModel;

class Task extends Model
{
    protected $primaryKey = 'task_id';

    protected $fillable = ['task_title','task_desc','status','priority','person_id','proj_title','proj_id','created_by'];

    public function project(){

        return $this->belongsTo('AppProject','proj_id');
    }
 

Заранее спасибо

Комментарии:

1. Какую ошибку вы получаете? Или записи просто не удаляются?

2. Записи не удаляются

Ответ №1:

Если у вас нет веских оснований называть столбцы так, как у вас есть, я бы предложил следовать соглашению и изменить ваши миграции на…

 Schema::create('tasks', function (Blueprint $table) {
    $table->increments('id');
    $table->unsignedInteger('project_id');
    // other columns...

    $table->foreign('project_id')
        ->references('id')->on('projects')
        ->onDelete('cascade');
});

Schema::create('projects', function (Blueprint $table) {
    $table->increments('id');
    // other columns...
});
 

У приращений не должно быть значения по умолчанию, поскольку оно является основным идентификатором и по умолчанию также не имеет знака.

Вам нужно будет обновить определения отношений в ваших моделях, если вы внесете вышеуказанные изменения. Это должно устранить вашу ошибку.

В качестве небольшого дополнения, довольно часто вам потребуется больше функциональности, чем просто каскадное удаление. Laravel предлагает события и прослушиватели, которые можно использовать для получения требуемого поведения — https://laravel.com/docs/5.8/eloquent#events . Это объясняет, как вы можете достичь того, что вам нужно, создав model observer.

Я бы рекомендовал потратить время на ознакомление с вышеизложенным. Хотя вы также можете получить те же результаты, добавив в свой Project класс следующий метод,

 protected static function boot() {
    parent::boot();

    static::deleting(function(Project $project) {
        $project->tasks()->delete();
    });
}
 

Комментарии:

1. Спасибо за ваш ответ, я рассмотрю это. Я добавил этот фрагмент кода, но получаю «SQLSTATE [42S22]: столбец не найден: 1054 неизвестных столбца ‘tasks.project_proj_id’ в ‘where clause’ »

2. Ах, либо обновите свой Project метод task() до tasks() (который лучше описывает отношения), либо измените код, который я опубликовал с tasks() на task() .

Ответ №2:

Вам просто нужен внешний ключ в proj_id таблицы задач, а не наоборот, поэтому сначала удалите внешний ключ в основном столбце проектов.

Кроме того, тип столбца внешней таблицы задач должен соответствовать первичному ключу в таблице проектов. Вам нужно использовать UnsignedInteger, поскольку приращения в таблице проектов создадут первичный ключ целого числа с автоматическим приращением без знака.

 $table->unsignedInteger('proj_id')->nullable()->default(null);
$table->foreign('proj_id')->references('proj_id')->on('projects')->onDelete('cascade');
 

Затем повторите миграцию, и она должна работать хорошо. Если у вас есть какие-либо ошибки, обновите свой ответ