插入/更新多对多关系时,背包无法传递正确的值

问题描述

我已经用第三个数据透视表在两个表之间建立了多对多关系。 使情况变得有些困难的是我根据名称而不是ID链接Apps表。这是因为我从第三方更新了应用程序列表,并且应用程序名称始终是一致的,如果某个时候删除了应用程序然后重新添加了ID,则ID可能会更改。

应用

  • id
  • name //这是应用程序的名称,对于特定的应用程序,它永远不会更改,并且简短,全小写,无空格且唯一
  • label //这是用户友好的名称

计划

apps_plans数据透视表

  • id
  • apps_name
  • plans_id

我终于可以在Laravel本身中使所有功能正常运行,但是我根本无法弄清楚如何使其在我的管理门户背包中正常工作。在我尝试更新或制定新计划之前,我已经理解到一切都能正常进行。我使用select2类型选择的应用程序会尝试将其插入具有ID号而不是名称的数据透视表中。

随机化一些名称,如果情况不尽相同,那是我的错误。在我完成的所有测试中,这方面都可以正常工作:

计划模型:

{
    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','name','id');
    }
}

**请注意,我删除了fillable变量,但我不想在列中公开所有变量。

背包计划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','pivot' => true,]);

为了使我的项目详细信息不公开,我删除了很多内容,希望这样做是有意义的。我认为所有重要细节仍在讨论中。有人知道背包是否有问题?还是我错过了某个选项,您可以在其中设置用于关系的哪一列。显然,它不是从模型中提取出来的,因为模型可以按预期的方式工作……

谢谢!

编辑:这是我正在使用的迁移,它可以完美运行-即使在PHPmyadmin中,它也提供了下拉菜单供您选择

    {
        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))"
}

同样,我删除了一些非常特定于我项目的细节,但我认为我没有更改错误消息中的任何逻辑。您可以看到关于查询的所有内容看起来都很不错,除了最后时,它正在插入App ID而不是应有的App名称

解决方法

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

由于nameapps表的关键,因此请考虑删除该表的自动递增ID并设置

在apps表的迁移中,执行以下操作:

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

然后在您的应用模型中,执行以下操作:

protected $primaryKey = 'name';

public $incrementing = false;

protected $keyType = 'string';

现在,Laravel(和代理背包)应该按照您期望的方式对待这种关系。

相关问答

Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其...
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。...
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbc...