inserting/updating 多对多关系时无法让背包传递正确的值
Can't get backpack to pass correct value when inserting/updating a many to many relationship
我在两个 table 之间创建了多对多关系,并带有第三个枢轴 table。
让情况变得有点困难的是我根据名称而不是 ID 链接应用程序 table。这是因为我从第三方更新应用列表,应用名称将始终保持一致,如果应用在某个时候被删除,然后重新添加等,ID 可能会发生变化。
应用
- id
- name // 这是应用程序的名称,它永远不会因特定应用程序而改变,并且很短,全部小写,没有空格,并且是唯一的
- label // 这是用户友好的名称
计划
- id
- 名字
- 等等
apps_plans 枢轴 table
- id
- apps_name
- plans_id
我终于让 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)应该按照您期望的方式处理这种关系。
我在两个 table 之间创建了多对多关系,并带有第三个枢轴 table。 让情况变得有点困难的是我根据名称而不是 ID 链接应用程序 table。这是因为我从第三方更新应用列表,应用名称将始终保持一致,如果应用在某个时候被删除,然后重新添加等,ID 可能会发生变化。
应用
- id
- name // 这是应用程序的名称,它永远不会因特定应用程序而改变,并且很短,全部小写,没有空格,并且是唯一的
- label // 这是用户友好的名称
计划
- id
- 名字
- 等等
apps_plans 枢轴 table
- id
- apps_name
- plans_id
我终于让 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)应该按照您期望的方式处理这种关系。