You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Laravel+Vue表单提交时如何将主键作为外键存入另一表?

问题描述

我有两张关联的数据表,希望通过单个表单提交数据时,自动将parties表新增记录的主键作为外键存入corraddresses的party_id字段,但目前提交时要么只有parties表存入数据,要么触发非空约束错误。以下是我的代码:

数据表迁移

parties表

public function up()
{
    Schema::create('parties', function (Blueprint $table) {
        $table->id();
        $table->string('full_name');
        $table->string('ic_passport');
        $table->string('nationality');
        $table->string('income_tax_no');
        $table->string('income_Tax_filing_branch');
        $table->string('phone_no');
        $table->string('email');
        $table->timestamps();
    });
}

corraddresses表

public function up()
{
    Schema::create('corraddresses', function (Blueprint $table) {
        $table->id();
        $table->unsignedBigInteger('party_id');
        $table->foreign('party_id')->references('id')->on('parties');
        $table->string('address_1');
        $table->string('address_2');
        $table->string('city');
        $table->string('poscode');
        $table->timestamps();
    });
}

模型代码

Party模型

class Party extends Model
{
use HasFactory;
protected $fillable = ['full_name','ic_passport','nationality','income_tax_no',
'income_Tax_filing_branch','phone_no','email'];
}

Corraddress模型

class Corraddress extends Model
{
use HasFactory;
protected $fillable = ['address_1','address_2','city','poscode','party_id'];

public function partyId()
{
    return $this->belongsTo(Party::class, 'party_id', 'id');
}
}

控制器代码

PartyController的store方法

public function store(Request $request)
{
    $party = Party::create($request->post());
    return response()->json([
        'message'=>'Party Created Successfully!!',
        'party'=>$party
    ]);
}

CorraddressController的store方法

public function store(Request $request)
{
    $corraddress = Corraddress::create($request->post());
    return response()->json([
        'message'=>'Corraddress Created Successfully!!',
        'corraddress'=>$corraddress
    ]);
}

前端表单脚本

data() {
return {
full_name: '',
ic_passport: '',
nationality: '',
income_tax_no: '',
income_Tax_filing_branch: '',
phone_no: '',
email: '',

address_1: '',
address_2: '',
city: '',
poscode: '',
party_id: '',
};
},
methods: {
addNewPost(){
            axios.post('/api/auth/party',{
                full_name: this.full_name,
                ic_passport: this.ic_passport,
                nationality: this.nationality,
                income_tax_no: this.income_tax_no,
                income_Tax_filing_branch: this.income_Tax_filing_branch,
                phone_no: this.phone_no,
                email: this.email,
            })
            axios.post('/api/auth/corraddress',{
                address_1: this.address_1,
                address_2: this.address_2,
                city: this.city,
                poscode: this.poscode,
                party_id: response.party.id,
                // party_id: this.party_id,
            })
},
},

当前问题

  • 保留party_id: response.party.id时,只有parties表存入数据,corraddresses无数据
  • 取消注释party_id: this.party_id时,触发SQL错误:
message "SQLSTATE[23000]: Integrity constraint violation: 1048 Column 'party_id' cannot be null (SQL: insert into `corraddresses` (`address_1`, `address_2`, `city`, `poscode`, `party_id`, `updated_at`, `created_at`) values (awgawg, awgawg, gawg, awgaw, ?, 2022-11-08 04:31:58, 2022-11-08 04:31:58))"

解决方案

问题核心在前端异步请求的顺序处理和变量作用域,同时可以优化模型关联规范:

1. 前端修复:处理异步请求依赖

axios请求是异步的,当前写法会同时发送两个请求,第二个请求无法获取第一个请求的返回结果,且response变量未定义。需要用async/await或then链式调用确保先创建Party,再用返回ID创建地址:

修改后的前端方法:

async addNewPost(){
    try {
        // 等待Party创建完成,获取返回数据
        const partyRes = await axios.post('/api/auth/party',{
            full_name: this.full_name,
            ic_passport: this.ic_passport,
            nationality: this.nationality,
            income_tax_no: this.income_tax_no,
            income_Tax_filing_branch: this.income_Tax_filing_branch,
            phone_no: this.phone_no,
            email: this.email,
        });
        
        // 使用返回的party ID创建地址
        await axios.post('/api/auth/corraddress',{
            address_1: this.address_1,
            address_2: this.address_2,
            city: this.city,
            poscode: this.poscode,
            party_id: partyRes.data.party.id,
        });
        
        alert('数据提交成功');
        // 重置表单
        Object.assign(this.$data, this.$options.data.call(this));
    } catch (err) {
        console.error('提交失败:', err);
        alert('提交出错,请重试');
    }
}

2. 模型关联优化(规范写法)

Corraddress模型的关联方法名建议改为party(符合Laravel命名规范),同时在Party模型添加反向关联:

// Corraddress模型修改关联方法
public function party()
{
    return $this->belongsTo(Party::class, 'party_id', 'id');
}

// Party模型添加反向关联
public function corraddresses()
{
    return $this->hasMany(Corraddress::class, 'party_id');
}

3. 可选:后端合并接口(简化逻辑)

可以在后端写统一接口,一次性处理两个表的创建,避免前端处理异步顺序,同时用事务保证数据一致性:

在PartyController新增方法:

use Illuminate\Support\Facades\DB;

public function storeWithAddress(Request $request)
{
    // 验证请求数据
    $validated = $request->validate([
        'full_name' => 'required|string',
        'ic_passport' => 'required|string',
        'nationality' => 'required|string',
        'income_tax_no' => 'required|string',
        'income_Tax_filing_branch' => 'required|string',
        'phone_no' => 'required|string',
        'email' => 'required|email',
        'address_1' => 'required|string',
        'address_2' => 'nullable|string',
        'city' => 'required|string',
        'poscode' => 'required|string',
    ]);
    
    // 事务确保数据要么都创建成功,要么都回滚
    DB::transaction(function () use ($validated) {
        $party = Party::create([
            'full_name' => $validated['full_name'],
            'ic_passport' => $validated['ic_passport'],
            'nationality' => $validated['nationality'],
            'income_tax_no' => $validated['income_tax_no'],
            'income_Tax_filing_branch' => $validated['income_Tax_filing_branch'],
            'phone_no' => $validated['phone_no'],
            'email' => $validated['email'],
        ]);
        
        // 通过关联创建地址,自动填充party_id
        $party->corraddresses()->create([
            'address_1' => $validated['address_1'],
            'address_2' => $validated['address_2'],
            'city' => $validated['city'],
            'poscode' => $validated['poscode'],
        ]);
    });
    
    return response()->json(['message' => 'Party及地址创建成功']);
}

前端只需发送一次请求:

async addNewPost(){
    try {
        await axios.post('/api/auth/party-with-address',{
            full_name: this.full_name,
            ic_passport: this.ic_passport,
            nationality: this.nationality,
            income_tax_no: this.income_tax_no,
            income_Tax_filing_branch: this.income_Tax_filing_branch,
            phone_no: this.phone_no,
            email: this.email,
            address_1: this.address_1,
            address_2: this.address_2,
            city: this.city,
            poscode: this.poscode,
        });
        alert('提交成功');
        this.$data = this.$options.data.call(this);
    } catch (err) {
        console.error(err);
        alert('提交失败');
    }
}

内容的提问来源于stack exchange,提问作者Sam

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.13 21:25:24