我正在尝试执行 2 次插入,在 2 个表中,表通过外键受到约束。这两个操作必须在事务内执行,以防止最终失败。 (实际上,我需要在更多表上执行更多插入,因此事务很重要;但本示例中的 2 个表足以复制问题)
数据库驱动程序是pgsql
SomeRepo.php(也尝试使用事务关闭变体)
DB::beginTransaction();
try {
$parentData = [
'name' => 'Parent name'
];
$parent = new Parent($parentData);
$parent->save();
$childData = [
// Tried it with and without setting "parent_id" here
'parent_id' => $parent->id,
'name' => 'Child name'
];
$child = new Child($childData);
$parent->children()->save($child);
DB::commit();
} catch (Exception $e) {
DB::rollback();
}
Parent.php
protected $fillable = [
'name'
];
public function children()
{
return $this->hasMany(Child::class);
}
Child.php
protected $fillable = [
'name', 'parent_id'
];
尝试插入子行时执行失败,并返回父 ID。
insert or update on table "child" violates foreign key constraint "child_parent_id_foreign"
编辑 子表SQL:
DROP TABLE IF EXISTS "public"."child";
CREATE TABLE "public"."child" (
"id" int4 NOT NULL DEFAULT nextval('child_id_seq'::regclass),
"parent_id" int4 NOT NULL,
"is_read" bool NOT NULL DEFAULT false,
"created_at" timestamp(0) DEFAULT now(),
"updated_at" timestamp(0),
"deleted_at" timestamp(0)
)
;
ALTER TABLE "public"."child" OWNER TO "my_user";
-- ----------------------------
-- Primary Key structure for table child
-- ----------------------------
ALTER TABLE "public"."child" ADD CONSTRAINT "child_pkey" PRIMARY KEY ("id");
-- ----------------------------
-- Foreign Keys structure for table child
-- ----------------------------
ALTER TABLE "public"."child" ADD CONSTRAINT "child_parent_id_fkey" FOREIGN KEY ("parent_id") REFERENCES "public"."parent" ("id") ON DELETE NO ACTION ON UPDATE NO ACTION DEFERRABLE INITIALLY DEFERRED;
要将数据保存在相关表中,请使用此
Parent::create(['name'=>'parent name']); //save in parent table
$lastId = Parent::query()->max('id'); //get last inserted row id
$parent = App\Parent::find($lastId);
$child = $parent->children()->create([
'message' => 'A new comment.',
]);
也可以使用
createMany
方法
$parent = App\Parent::find($lastId);
$parent->children()->createMany([
[
'message' => 'A new comment.',
],
[
'message' => 'Another new comment.',
],
]);
通过在父模型的关系上使用
create
和 createMany
来尝试使用此代码:
// Create the parent object.
$parent = Parent::create([
'name' => 'Parent 1'
]);
// Insert one.
$child = $parent->children()->create([
'name' => 'Child 1',
]);
// Insert many.
$parent->children()->createMany([
[
'name' => 'Child 2',
],
[
'name' => 'Child 3',
],
]);
你可以试试这个
try {
DB::beginTransaction();
$parent = Parent::create([
'name' => 'Parent name'
]);
$parent->children()->create([
'parent_id' => $parent->id,
'name' => 'Child name'
]);
DB::commit();
} catch (Exception $e) {
DB::rollback();
}
更改外键——在数据库上运行此sql
alter table child drop constraint child_parent_id;
alter table child add foreign key (parent_id) references parent(id) deferrable initially deferred;
这将允许您以任意顺序创建子级或父级,并且在提交之前约束不会被验证。在这种情况下,这不是必需的——但是,这确实取决于您的 ID 的生成方式。
我没有测试,但我认为数据库方法 'DB::table('---')->insert()' 可以适合您的情况
children 函数需要一个中间表,将其更改为:
public function children()
{
return $this->belongsToMany(Child::class);
}
并且不要这样做
$parent->children()->save($child);
。
或者如果您想这样做,请制作
child_parent
表,其中包含 2 个字段 child_id
和 parent_id
。