问题描述
我已经用第三个数据透视表在两个表之间建立了多对多关系。 使情况变得有些困难的是我根据名称而不是ID链接Apps表。这是因为我从第三方更新了应用程序列表,并且应用程序名称始终是一致的,如果某个时候删除了应用程序然后重新添加了ID,则ID可能会更改。
应用
计划
- id
- 名称
- 等
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);
之类的内容会导致相同的错误。
由于name
是apps
表的关键,因此请考虑删除该表的自动递增ID并设置
在apps表的迁移中,执行以下操作:
$table->string('name')->primary();
然后在您的应用模型中,执行以下操作:
protected $primaryKey = 'name';
public $incrementing = false;
protected $keyType = 'string';
现在,Laravel(和代理背包)应该按照您期望的方式对待这种关系。