Laravel Отношение «многие ко многим» не подходит для одной модели, но не для другой - PullRequest
0 голосов
/ 02 февраля 2020

У меня есть начало Laravel приложения только с двумя моделями: Пользователь и Проект. Между Пользователями и Проектами существует отношение многие ко многим, один Пользователь может работать над многими Проектами, а один Проект может работать со многими Пользователями.

Проблема, с которой я столкнулся, проявилась двумя способами:

  1. После миграции и заполнения моей БД с основными данными c я вручную создаю строку в сводной таблице project_user, связывая ссылки на первые записи * 1007. * и projects таблицы: INSERT INTO project_user (user_id, project_id) VALUES (1, 1). Затем я загружаю Тинкер, чтобы проверить отношения. Доступ ко всем проектам через модель User работает должным образом: User::find(1)->projects (возвращает действительную коллекцию моделей Project), однако обратное соотношение: Project::find(1)->users возвращает пустую коллекцию, когда она должна возвращать модель User, указанную в сводной таблице. таблица.
  2. И при использовании файла Seeder для заполнения таблицы project_user, например, так:
public function run()
{
    $project = Project::first();
    $admin = User::first();

    if (isset($project) && isset($admin)) {
        echo "Project: $project\n";
        echo "User: $admin\n";
        // FIXME: Why isn't this working?
        $project->users()->attach($admin);
        // The inverse below also fails for the same reason
        // $admin->projects()->attach($project);
    }
}

, что приводит к сбою файла заполнения с ошибкой: SQLSTATE[23000]: Integrity constraint violation: 1048 Column 'project_id' cannot be null (SQL: insert into project_user ( create_at , project_id , updated_at , user_id ) values (2020-02-02 17:01:04, ?, 2020-02-02 17:01:04, 1))

Я искал свой код, а inte rnet ищет решение, но безрезультатно , Проблема должна заключаться в крошечной ошибке в моем коде, неправильном использовании какой-либо функции или неправильном порядке операций. Для меня ясно, что должна быть проблема с ассоциацией на стороне проекта, но я буквально сравнивал пользователей и проекты на каждом шагу, и я не могу понять, в чем дело. Я вставлю соответствующие разделы кода ниже, и если есть какая-либо дополнительная информация или код, который я могу предоставить, я более чем рад это сделать. Заранее благодарим за помощь!

Вот определения модели:

class User extends Authenticatable
{
    public $type;

    // Here is the relationship to the Projects this User is working on
    public function projects()
    {
        // SELECT * FROM project_user WHERE user_id = $user->id
        return $this->belongsToMany(Project::class)->withTimestamps();
    }


    use Notifiable;

    protected $fillable = [
        'name', 'email', 'password',
    ];

    protected $hidden = [
        'password', 'remember_token',
    ];

    protected $casts = [
        'email_verified_at' => 'datetime',
    ];
}
class Project extends Model
{
    public $id;

    public $name;

    public $deleted_at;

    // Here is the relationship to the Users working on this Project
    public function users()
    {
        // SELECT * FROM project_user WHERE project_id = $project->id
        return $this->belongsToMany(User::class)
            ->withTimestamps();
    }

    protected $fillable = [
        'name',
    ];

    protected $casts = [
        'deleted_at' => 'datetime',
    ];
}

Миграции таблиц users и projects:

public function up()
{
    Schema::create('users', function (Blueprint $table) {
        $table->bigIncrements('id');
        $table->string('name');
        $table->string('email')->unique();
        $table->enum('type', ['admin', 'client', 'editor'])->default('client');
        $table->timestamp('email_verified_at')->nullable();
        $table->string('password');
        $table->rememberToken();
        $table->timestamps();
    });
}
public function up()
{
    Schema::create('projects', function (Blueprint $table) {
        $table->bigIncrements('id');
        $table->string('name')->unique();
        $table->integer('memberCount')->default(0)->nullable(false);
        $table->timestamp('deleted_at')->nullable();
        $table->timestamps();
    });
}

А вот сводная таблица project_user миграции, которая устанавливает ссылки:

public function up()
{
    Schema::create('project_user', function(Blueprint $table) {
        $table->bigIncrements('id');
        $table->unsignedBigInteger('user_id');
        $table->unsignedBigInteger('project_id');
        $table->timestamps();

        $table->unique(['user_id', 'project_id']);
        $table->foreign('user_id')->references('id')->on('users')->onDelete('cascade');
        $table->foreign('project_id')->references('id')->on('projects')->onDelete('cascade');
    });
}

1 Ответ

1 голос
/ 02 февраля 2020

Попробуйте удалить public $id; из вашей модели Project (и других избыточных свойств). С Eloquent вам не нужно объявлять свойства модели, которые существуют в виде столбцов в вспомогательной таблице модели. Я полагаю, что происходит то, что вызывается свойство $id в вашей модели Project, которое является нулевым, поскольку оно переопределяет магический приемник c, который Eloquent предоставит для этого столбца из коробки.

Если вы объявляете свойства в своей модели, чтобы ваша IDE подобрала их, рассмотрите возможность использования пакета barryvdh / laravel -ide-helper .

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...