Laravel 多对多关系字段名称

Laravel Many-to-Many Relationship Field Names

我有一个用户 table 和一个权限 table。一个用户可以有多个权限,一个权限可以有多个用户:

USER ID | PERMISSION ID
1 | 1
1 | 2
2 | 1
2 | 1

根据 Laravel 规范的定义,有一个名为 permission_user 的链接 table,用于自动推断这些 table。

如果我定义如下函数:

用户模型:

    public function Permissions()
    {
        return $this->belongsToMany('App\Permission');
    }

权限模型:

   public function Users()
   {
       return $this->belongsToMany('App\User');
   }


调用 App\User::first()->Permissions()->attach(App\Permission::first()); 时出现错误

 Illuminate\Database\QueryException  : SQLSTATE[42S22]: Column not found: 1054 Unknown column '' in 'field list' (SQL: insert into `permission_user` (``, `user_id`) values (3, 1))

数据库迁移文件:

<?php

use Illuminate\Support\Facades\Schema;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;
use Carbon\Carbon;
use App\User;
use App\Permission;
use App\Http\Resources\User as UserResource;
class CreateUsersTable extends Migration
{
    /**
     * Run the migrations.
     *
     * @return void
     */
    public function up()
    {
        Schema::create('permissions', function (Blueprint $table) {
            $table->bigIncrements('id');
            $table->string('name');
            $table->timestamps();
        });

        Schema::create('users', function (Blueprint $table) {
            $table->bigIncrements('id');
            $table->string('username')->unique();
            $table->string('name')->unique();
            $table->string('email')->unique();
            $table->boolean('verified');
            $table->timestamps();
        });


        Schema::create('permission_user', function (Blueprint $table) {
            $table->bigIncrements('id');
            $table->unsignedBigInteger('permission_id');
            $table->unsignedBigInteger('user_id');
            $table->timestamps();
            $table->foreign('permission_id')->references('id')->on('permissions');
            $table->foreign('user_id')->references('id')->on('users');
        });

        $this->add_permission('View Projects');
        $this->add_permission('Edit Projects');
        $this->add_permission('View Users');
        $this->add_permission('Edit Users');

        $user = new User();
        $user->name = 'John Smith';
        $user->email = 'john@smith.com';
        $user->username = 'jsmith';
        $user->verified = 1;
        $user->save();


        $user->permissions()->attach(Permission::where('name','View Users')->first()->id); // -> This line it can't tell that permission_user.permission_id is where the permission.id field goes;

        $perms  = $user->permissions()->get();

        foreach($perms as $perm)
        {
            echo $perm->name . '\n';
        }

    }

    /**
     * Reverse the migrations.
     *
     * @return void
     */
    public function down()
    {
        DB::statement('SET FOREIGN_KEY_CHECKS = 0');
        Schema::dropIfExists('permission_user');
        Schema::dropIfExists('project_user');
        Schema::dropIfExists('permissions');
        Schema::dropIfExists('deployment_log');
        Schema::dropIfExists('branches');
        Schema::dropIfExists('projects');
        Schema::dropIfExists('users');
        DB::statement('SET FOREIGN_KEY_CHECKS = 1');
    }

    private function add_permission($permission_name)
    {
        DB::table('permissions')->insert(
            array(
                'name' => $permission_name,
            )
        );
    }
}

看来 Laravel(5.8) 无法从链接 table 中辨别出 permission_id 是对 permission.id 字段的外部引用的字段,即使数据库迁移反映出 user_id 是对 user.id 的外部引用,而 permission_id 是对 permission.id.

的外部引用

我可以通过在 belongsToMany 函数中指定链接 table 名称、字段名称和外键名称来解决这个问题,但是,Laravel 自己的文档指出不需要这样做当 tables 和字段被适当命名时,我的就是。这是 Laravel 中的错误吗?我需要更改 permission_user.permission_id 字段的名称吗?我该如何解决这个问题而不必在我的模型中指定这些名称,因为根据 Laravel(5.8) 的文档,这很耗时而且不需要。

根据 laravel 文档:

[...] Many users may have the role of "Admin". To define this relationship, three database tables are needed: users, roles, and role_user. The role_user table is derived from the alphabetical order of the related model names, and contains the user_id and role_id columns.

链接 table 必须仅包含每个模型的外键。否则,您需要指定正在使用的关系 table 以及每个关系模型的主键,如 laravel 文档中所指定。

正如我在评论部分所说,如果您创建 permission_user table 只有 permission_iduser_id 列并将此列作为主键,它将按预期工作:

Schema::create('permission_user', function (Blueprint $table) {
    $table->unsignedBigInteger('permission_id');
    $table->unsignedBigInteger('user_id');
    $table->foreign('permission_id')->references('id')->on('permissions');
    $table->foreign('user_id')->references('id')->on('users');

    $table->primary(['permission_id', 'user_id']);
});

Here is a package that i have developed to handle user permissions and you can check the user_has_permissions table definition, which is, basically, a table that does exactly what your permission_user table does, by clicking this link.

希望对您有所帮助。