【问题标题】:Laravel Many-to-Many Relationship Field NamesLaravel 多对多关系字段名称
【发布时间】:2020-01-09 19:12:53
【问题描述】:

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

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

Laravel 规范定义了一个名为 permission_user 的链接表,用于自动推断这些表。

如果我定义以下函数:

用户模型:

    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) 无法从链接表中辨别出 permission_id 是对 permission.id 字段的外部引用的字段,即使数据库迁移反映 user_id 是对 user.id 和 permission_id 的外部引用是对permission.id 的外部引用。

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

【问题讨论】:

  • 您的数据库中是否存在权限?它们是实际存储的吗?
  • 您是否尝试使用仅包含 user_idpermission_id 字段且没有时间戳和 ID 的 permission_user 表?另外,将user_idpermission_id 都设置为该表的主键。
  • 你能发布你的完整权限模型吗?
  • @MateusJunges 看起来解决了它。我在带有时间戳的链接表上有一个主键 ID,不知道为什么这很重要,因为这是非常标准的东西。
  • 要按预期工作,链接表必须只包含关系的每个模型的主键。如果您需要这些附加列,则必须在定义 belongsToMany 关系时指定您的关系表和每个表的主键。

标签: laravel eloquent eloquent-relationship


【解决方案1】:

根据 laravel 文档:

[...] 许多用户可能具有“管理员”角色。要定义这种关系,需要三个数据库表:usersrolesrole_userrole_user 表派生自相关模型名称的字母顺序,并包含 user_idrole_id 列。

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

正如我在 cmets 部分中所说,如果您创建的 permission_user 表仅包含 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 是我为处理用户权限而开发的一个包,您可以通过单击@987654322 检查user_has_permissions 表定义,基本上,该表与您的permission_user 表完全相同。 @。

希望对你有帮助。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-08-12
    • 1970-01-01
    • 1970-01-01
    • 2020-07-15
    • 2018-06-15
    • 2018-01-22
    相关资源
    最近更新 更多