Laravel 7, SQLSTATE [23000]: Integridade violação de restrição: 19 restrição NOT NULL falhou ao tentar adicionar um relacionamento

NTIC:

Estou correndo Laravel 7 no PHP 7.4 com o MySQL 8.0.

Eu tenho três tabelas, User, Companye Department, com seus respectivos modelos e fábricas.

Eu criei um teste onde eu estou adicionando a relação:

// 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();

Estou tendo o erro a seguir: 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))

Meu esquema de tabela é definida assim:

// 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();
});

É meu entendimento que não deve haver valores nulos no SQL-tabelas, que é por isso que estou deliberadamente tentando evitar ->nullable()nos meus migrações. Especialmente para as chaves estrangeiras como estes.

EDITAR:

Eu tentei fazê-lo desta maneira, eu também fez uma tabela dinâmica para users_companies. Agora eu posso anexar uma empresa, mas eu ainda estou recebendo um erro SQL quando fazer o teste desta maneira:

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

$user->companies()->attach($company);
$company->departments()->create([
    'name' => 'Department 1',
    'contact_email' => '[email protected]',
    'contact_phone' => '123456789',
]);

Isso também falha com o erro indicado abaixo:

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

O erro é o seguinte: 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, [email protected], '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' => '[email protected]',
        'contact_phone' => '123456789',
    ];
});

Fábricas

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' => '[email protected]',
        'contact_phone' => '123456789',
    ];
});
miken32:

Alguns problemas com a estrutura da tabela são muito claros à primeira vista.

  • Parece que você está tentando adicionar uma user_idcoluna para a sua companiesmesa. Esta não é uma boa idéia, assumindo as suas empresas têm mais de um empregado.
  • Se você quiser usar NOT NULLcolunas, é melhor definir um valor padrão para cada um deles.

Assim, podemos começar por escrever o migrações algo assim, incluindo tabelas dinâmicas para as relações empresa / usuário e do departamento / utilizador:

// 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');
});

Agora temos ligações entre tabelas. Um departamento é parte de uma empresa; um usuário pode fazer parte de vários departamentos e / ou várias empresas. Isto leva às seguintes relações :

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);
    }
}

Agora código como este deve funcionar:

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

$user->companies()->attach($company);
$company->departments()->create([
    'name' => 'Department 1',
    'contact_email' => '[email protected]',
    'contact_phone' => '123456789',
]);

Especificamente, o attachmétodo é usado para atualizar muitos-para-muitos relacionamentos, o que você não parecem ter definido, com base em seu layout tabela original.

Acho que você gosta

Origin http://43.154.161.224:23101/article/api/json?id=280056&siteId=1
Recomendado
Clasificación