簡體   English   中英

Laravel 7,SQLSTATE[23000]:完整性約束違規:19 NOT NULL 約束在嘗試添加關系時失敗

[英]Laravel 7, SQLSTATE[23000]: Integrity constraint violation: 19 NOT NULL constraint failed when trying to add a relationship

我在 PHP 7.4 和 MySQL 8.0 上運行 Laravel 7。

我有三個表, UserCompanyDepartment ,以及它們各自的模型和工廠。

我創建了一個測試,我在其中添加了關系:

// MyTest.php
$user = factory(User::class)->create();

$company = factory(Company::class)->make();
$company->user()->associate($user);
$company->create(); // it fails here because of NOT NULL constraint, companies.user_id

$department = factory(Department::class)->make();
$department->company()->associate($company);
$department->create();

我收到以下錯誤: Integrity constraint violation: 19 NOT NULL constraint failed: companies.user_id (SQL: insert into "companies" ("updated_at", "created_at") values (2020-03-10 07:27:51, 2020-03-10 07:27:51))

我的表架構是這樣定義的:

// users
Schema::create('users', function (Blueprint $table) {
    $table->id();
    $table->string('name');
    $table->string('email')->unique();
    $table->timestamp('email_verified_at')->nullable();
    $table->string('phone');
    $table->integer('user_type');
    $table->string('password');
    $table->rememberToken();
    $table->timestamps();
});

// companies
Schema::create('companies', function (Blueprint $table) {
    $table->id();
    $table->foreignId('user_id')->constrained()->onDelete('cascade');
    $table->string('name');
    $table->string('contact_email');
    $table->string('contact_phone');
    $table->timestamps();
});

// departments
Schema::create('departments', function (Blueprint $table) {
    $table->id();
    $table->foreignId('company_id')->constrained()->onDelete('cascade');
    $table->string('name');
    $table->string('contact_email');
    $table->string('contact_phone');
    $table->timestamps();
});

我的理解是 SQL 表中不應該有 NULL 值,這就是為什么我特意在遷移中避免->nullable() 特別是對於像這樣的外鍵。

編輯:

我嘗試這樣做,我還為users_companies制作了一個數據透視表。 現在我可以附加一個公司,但是在以這種方式進行測試時我仍然遇到 SQL 錯誤:

$user = factory(User::class)->create();
$company = factory(Company::class)->create();

$user->companies()->attach($company);
$company->departments()->create([
    'name' => 'Department 1',
    'contact_email' => 'department1@example.test',
    'contact_phone' => '123456789',
]);

這也失敗並出現以下錯誤:

$company = factory(Company::class)->create();
$company->departments()->save(factory(Department::class)->make());

錯誤是這樣的: Integrity constraint violation: 19 NOT NULL constraint failed: departments.company_id (SQL: insert into "departments" ("name", "contact_email", "contact_phone", "company_id", "updated_at", "created_at") values (Department 1, department1@example.test, '123456789', ?, 2020-03-11 07:59:31, 2020-03-11 07:59:31))

CompanyFactory.php

<?php

/** @var \Illuminate\Database\Eloquent\Factory $factory */

use App\Company;
use Faker\Generator as Faker;

$factory->define(Company::class, function (Faker $faker) {
    return [
        'name' => 'Company 1',
        'contact_email' => 'company@example.test',
        'contact_phone' => '123456789',
    ];
});

工廠

DepartmentFactory.php

<?php

/** @var \Illuminate\Database\Eloquent\Factory $factory */

use App\Department;
use Faker\Generator as Faker;

$factory->define(Department::class, function (Faker $faker) {
    return [
        'name' => 'Department 1',
        'contact_email' => 'department1@example.test',
        'contact_phone' => '123456789',
    ];
});

乍一看,您的表結構的一些問題非常清楚。

  • 您似乎正在嘗試將user_id列添加到您的companies表中。 這不是一個好主意,假設您的公司有不止一名員工。
  • 如果要使用NOT NULL列,最好為每個列定義一個默認值

所以我們可以從編寫這樣的遷移開始,包括公司/用戶和部門/用戶關系的數據透視表:

// companies
Schema::create('companies', function (Blueprint $table) {
    $table->id();
    $table->string('name');
    $table->string('contact_email')->default('');
    $table->string('contact_phone')->default('');
    $table->timestamps();
});

// departments
Schema::create('departments', function (Blueprint $table) {
    $table->id();
    $table->foreignId('company_id')->constrained()->onDelete('cascade');
    $table->string('name');
    $table->string('contact_email')->default('');
    $table->string('contact_phone')->default('');
    $table->timestamps();
});

// users
Schema::create('users', function (Blueprint $table) {
    $table->id();
    $table->string('email')->unique();
    $table->timestamp('email_verified_at')->nullable();
    $table->string('name')->default('');
    $table->string('phone')->default('');
    $table->integer('user_type')->default(0);
    $table->string('password');
    $table->rememberToken();
    $table->timestamps();
});

Schema::create('company_user', function (Blueprint $table) {
    $table->id();
    $table->foreignId('user_id')->constrained()->onDelete('cascade');
    $table->foreignId('company_id')->constrained()->onDelete('cascade');
});

Schema::create('department_user', function (Blueprint $table) {
    $table->id();
    $table->foreignId('user_id')->constrained()->onDelete('cascade');
    $table->foreignId('department_id')->constrained()->onDelete('cascade');
});

現在我們有了表之間的鏈接。 部門是公司的一部分; 一個用戶可以是多個部門和/或多個公司的一部分。 這導致以下關系

class User extends Model {
    // many-to-many
    public function companies() {
        return $this->belongsToMany(App\Company::class);
    }
    // many-to-many
    public function departments() {
        return $this->belongsToMany(App\Department::class);
    }
}

class Company extends Model {
    public function departments() {
        // one-to-many
        return $this->hasMany(App\Department::class);
    }
    public function users() {
        // many-to-many
        return $this->belongsToMany(App\User::class);
    }
}

class Department extends Model {
    public function company() {
        // one-to-many (inverse)
        return $this->belongsTo(App\Company::class);
    }
    public function users() {
        // many-to-many
        return $this->belongsToMany(App\User::class);
    }
}

現在這樣的代碼應該可以工作:

$user = factory(User::class)->create();
$company = factory(Company::class)->create();

$user->companies()->attach($company);
$company->departments()->create([
    'name' => 'Department 1',
    'contact_email' => 'department1@example.test',
    'contact_phone' => '123456789',
]);

具體來說, attach方法用於更新多對多關系,您似乎沒有根據原始表格布局定義這些關系。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM