inserting/updating 多对多关系时无法让背包传递正确的值

Can't get backpack to pass correct value when inserting/updating a many to many relationship

我在两个 table 之间创建了多对多关系,并带有第三个枢轴 table。 让情况变得有点困难的是我根据名称而不是 ID 链接应用程序 table。这是因为我从第三方更新应用列表,应用名称将始终保持一致,如果应用在某个时候被删除,然后重新添加等,ID 可能会发生变化。

应用

计划

apps_plans 枢轴 table

我终于让 Laravel 本身的一切都完美运行,但我完全不知道如何让它在我的管理门户的 Backpack 中正常运行。在我尝试更新或创建新计划之前,我已经达到了一切正常的地步。我 select 使用 select2 类型的应用程序,它尝试使用 ID 号而不是名称将它们插入枢轴 table。

随机命名一些名字,如果事情不完全匹配是我的错误。从我所做的所有测试来看,这方面工作正常:

计划型号:

{
    use CrudTrait;
    protected $table = 'plans';
    protected $guarded = ['id'];



    public function apps()
    {
        return $this->belongsToMany('App\Apps', 'apps_plans', 'plans_id', 'apps_name', 'id', 'name');
    }
}

应用模型:

    class Apps extends Model
{
    use CrudTrait;
    protected $table = 'apps';
    protected $guarded = ['id'];

    protected $casts = [
        'json' => 'array',
    ];

    public function plans()
    {
        return $this->belongsToMany('App\Plan', 'apps_plans', 'apps_name', 'plans_id', 'name', 'id');
    }
}

**注意我删除了可填充变量,我不想在我的列中公开所有变量。

背包计划 CrudController:

    public function setup()
    {
        CRUD::setModel(\App\Plan::class);
        CRUD::setRoute(config('backpack.base.route_prefix') . '/plan');
        CRUD::setEntityNameStrings('plan', 'plans');

        $this->crud->addColumn([
            'name' => 'apps',
            'type' => 'relationship',
            'label' => 'Apps',
            'entity' => 'apps',
            'attribute' => 'label',
            'model' => \App\Apps::class,
        ]);
    }


    protected function setupCreateOperation()
    {
        CRUD::setValidation(PlanRequest::class);

        CRUD::setFromDb(); // fields
       
        $this->crud->addField('apps', [
            'name' => 'apps',
            'type' => 'select2_multiple',
            'entity' => 'apps',
            'attribute' => 'label',
            'label' => 'Apps',
            'pivot' => true,
        ]);

为了保密我的项目细节,我删除了很多内容,我希望它有意义。我认为所有重要的细节都还在。有人知道这是否是 Backpack 的问题吗?或者我是否在某处错过了一个选项,您可以在其中设置它用于关系的列。它显然不是从模型中提取它,因为模型按照自己的预期工作......

谢谢!

编辑:这是我正在使用的迁移,它可以完美运行——即使在 phpmyadmin 中,它也会给我从

到 select 的项目下拉列表
    {
        Schema::create('apps_plans', function (Blueprint $table) {
            $table->id();
            $table->string('apps_name');
            $table->foreign('apps_name')->references('name')->on('apps');
            $table->unsignedBigInteger('plans_id');
            $table->foreign('plans_id')->references('id')->on('plans');
        });
    }

编辑 2:

这是我在尝试创建或更新时遇到的错误:


{
"error": "There is a problem with your request",
"message": "SQLSTATE[23000]: Integrity constraint violation: 1452 Cannot add or update a child row: a foreign key constraint fails (`api`.`apps_plans`, CONSTRAINT `apps_plans_apps_name_foreign` FOREIGN KEY (`apps_name`) REFERENCES `apps` (`name`)) (SQL: insert into `apps_plans` (`apps_name`, `plans_id`) values (2, 4))"
}

我再次删除了一些非常针对我的项目的细节,但我认为我没有更改错误消息中的任何逻辑。您可以看到查询的一切看起来都很棒,除了在最后,它插入了应用程序 ID 而不是应用程序名称。

我怀疑当前的配置直接在Laravel中会有相同的结果。即 运行 类似 $plan = Plan::find($somePlanId); $app = App::find($someAppId); $plan->apps()->attach($app); 的内容会导致相同的错误。

因为 name 是对 apps table 很重要的键,请考虑删除那个 table 的自动递增 ID,而不是设置

在应用 table 的迁移中,执行:

$table->string('name')->primary();

然后在您的应用程序模型中,执行:

protected $primaryKey = 'name';

public $incrementing = false;

protected $keyType = 'string';

现在,Laravel(以及代理 Backpack)应该按照您期望的方式处理这种关系。