Laravel 7, SQLSTATE [23000]: Integridad violación de restricción: 19 restricción NOT NULL fracasó al intentar agregar una relación

NTIC:

Estoy corriendo laravel 7 en PHP 7.4 con MySQL 8.0.

Tengo tres tablas, User, Companyy Department, con sus respectivos modelos y las fábricas.

He creado una prueba en la que estoy añadiendo la relación:

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

Obtuve el siguiente error: 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))

Mi esquema de la tabla se define así:

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

Es mi entendimiento de que no debe haber valores NULL en SQL-mesas, por lo que estoy tratando de evitar deliberadamente ->nullable()en mis migraciones. Especialmente para las claves externas como estos.

EDITAR:

He intentado hacerlo de esta manera, también hice una tabla dinámica para users_companies. Ahora puedo adjuntar una empresa, pero sigo teniendo un SQL-error cuando se hace la prueba de la siguiente manera:

$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',
]);

Esto también se produce el error se indica a continuación:

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

El error es el siguiente: 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',
    ];
});

Suerte

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:

Algunos problemas con su estructura de la tabla son muy claras a primera vista.

  • Parece que está tratando de agregar una user_idcolumna a la companiestabla. Esto no es una buena idea, suponiendo que sus empresas tienen más de un empleado.
  • Si desea utilizar NOT NULLcolumnas, que le define mejor un valor por defecto para cada uno de ellos.

Así que podemos empezar por escribir el migraciones algo como esto, incluyendo tablas dinámicas de las relaciones empresa / usuario y el departamento / usuario:

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

Ahora tenemos enlaces entre tablas. Un departamento es parte de una empresa; un usuario puede formar parte de varios departamentos y / o múltiples empresas. Esto conduce a las siguientes relaciones :

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

Ahora código como esto debería 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',
]);

En concreto, el attachmétodo se utiliza para la actualización de muchos-a-muchos relaciones, que no parecía haber definido, basado en el diseño original de la tabla.

Supongo que te gusta

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