简体   繁体   English

Laravel 多对多关系对一个模型失败,但对另一个模型没有

[英]Laravel Many-To-Many Relationship Fails For One Model But Not The Other

I have the beginnings of a Laravel application with only two models: User and Project.我有一个 Laravel 应用程序的开始,只有两个模型:用户和项目。 There is a many-to-many relationship between Users and Projects, A single User can be working on many Projects, and a single Project can be worked on by many Users.用户和项目之间存在多对多关系,一个用户可以处理多个项目,一个项目可以由多个用户处理。

The problem I'm experiencing has manifested itself in two ways:我遇到的问题以两种方式表现出来:

  1. After migrating and seeding my DB with basic data, I manually create a row in the project_user pivot table, linking references to the first entries of the users and projects tables: INSERT INTO project_user (user_id, project_id) VALUES (1, 1) .使用基本数据迁移和播种我的数据库后,我在project_user数据透视表中手动创建一行,将引用链接到usersprojects表的第一个条目: INSERT INTO project_user (user_id, project_id) VALUES (1, 1) I then boot up Tinker in order to test the relationship.然后我启动 Tinker 以测试这种关系。 Accessing all Projects through the User model works as expected: User::find(1)->projects (returns a valid collection of Project models), however, the inverse relationship: Project::find(1)->users returns an empty collection, when it should be returning the User model referenced in the pivot table.通过 User 模型访问所有项目按预期工作: User::find(1)->projects (返回项目模型的有效集合),但是,相反的关系: Project::find(1)->users返回一个空集合,当它应该返回数据透视表中引用的用户模型时。
  2. And, when using a Seeder file to seed the project_user table like so:并且,当使用 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);
    }
}

Which causes the seed file to fail with the error: SQLSTATE[23000]: Integrity constraint violation: 1048 Column 'project_id' cannot be null (SQL: insert into project_user ( created_at , project_id , updated_at , user_id ) values (2020-02-02 17:01:04, ?, 2020-02-02 17:01:04, 1))这导致种子文件失败并出现错误: SQLSTATE[23000]: Integrity constraint violation: 1048 Column 'project_id' cannot be null (SQL: insert into project_user ( created_at , project_id , updated_at , user_id ) values (2020-02-02 17:01:04, ?, 2020-02-02 17:01:04, 1))

I've scoured my code, as well as the internet looking for a solution, to no avail.我已经搜索了我的代码以及互联网寻找解决方案,但无济于事。 The problem must either be some very tiny mistake in my code, improper use of some function, or invalid order of operations.问题一定是我的代码中有一些非常小的错误,某些函数使用不当,或者操作顺序无效。 It's clear to me that there must be a problem with the association on the Project side, but I've literally compared Users and Projects side-by-side at every step and I can't figure out what's wrong.我很清楚,项目端的关联肯定有问题,但我确实在每一步都并排比较了用户和项目,我无法弄清楚出了什么问题。 I'll paste the relevant code sections below, and if there's any additional information or code I can provide, I'm more than happy to do so.我将粘贴下面的相关代码部分,如果我可以提供任何其他信息或代码,我非常乐意这样做。 Thanks in advance for your help!在此先感谢您的帮助!

Here are the model definitions:以下是模型定义:

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

The users and projects table migrations: usersprojects表迁移:

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

And here is the pivot table project_user migration that sets the references:这是设置引用的数据透视表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');
    });
}

Try removing public $id;尝试删除public $id; from your Project model (and the other redundant properties).从您的Project模型(和其他冗余属性)。 With Eloquent, you don't need to declare the model properties that exist as columns in the backing table of the model.使用 Eloquent,您无需声明作为模型支持表中的列存在的模型属性。 I believe what's happening is the $id property on your Project model is being called, which is null, because it is overriding the magic getter that Eloquent will provide for this column out of the box.我相信正在发生的事情是正在调用Project模型上的$id属性,该属性为空,因为它覆盖了 Eloquent 为该列提供的开箱即用的魔法 getter。

If you're declaring the properties on your model so your IDE picks them up, consider using the barryvdh/laravel-ide-helper package instead.如果您在模型上声明属性以便 IDE 获取它们,请考虑改用barryvdh/laravel-ide-helper包。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM