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

Laravel Eloquent使用UUID作为ID时部分关联返回NULL问题

问题排查:Laravel UUID关联部分返回NULL的问题

在Laravel ^9.19版本中,使用\Str::uuid()生成UUID作为AffiliatorVoucher模型的ID,但部分AffiliatorVoucherMember关联的voucher返回NULL,尽管对应ID的凭证确实存在,另一部分关联却能正常运行。

结果打印代码

dump(\App\Models\AffiliatorVoucher::find('27a4093d-2370-4c55-bc44-1f8ef8144067')->toArray());
dd(\App\Models\AffiliatorVoucherMember::with('voucher')->find(172)->toArray());

模型代码

App\Models\AffiliatorVoucher

class AffiliatorVoucher extends Model
{
    use HasFactory, SoftDeletes;

    protected $guarded = [
        'id',
    ];

    protected $casts = [
        'detail' => 'object',
    ];

    public $incrementing = false;


    public function members() :HasMany
    {
        return $this->hasMany(AffiliatorVoucherMember::class);
    }

    // ... other methods
}

App\Models\AffiliatorVoucherMember

class AffiliatorVoucherMember extends Model
{
    use HasFactory;

    protected $guarded = ['id'];

    
    protected $casts = [
        'detail' => 'object',
    ];

    
    public function voucher() :BelongsTo
    {
        return $this->belongsTo(AffiliatorVoucher::class, 'affiliator_voucher_id');
    }
}

迁移文件

Affiliator Vouchers迁移

public function up()
{
    Schema::create('affiliator_vouchers', function (Blueprint $table) {
        $table->uuid('id')->primary();
        $table->foreignId('affiliator_id')->constrained()->onUpdate('cascade')->onDelete('cascade');
        $table->foreignId('organization_id')->nullable()->constrained()->onUpdate('cascade')->onDelete('cascade');
        $table->string('prefix')->nullable();
        $table->string('code')->unique();
        $table->tinyInteger('status')->default(1);
        $table->bigInteger('discount_amount')->unsigned()->nullable();
        $table->decimal('discount_percentage', 5, 2)->unsigned()->nullable();
        $table->json('detail')->nullable();
        $table->timestamps();
        $table->softDeletes();
    });
}

Affiliator Voucher Member迁移

public function up()
{
    Schema::create('affiliator_voucher_members', function (Blueprint $table) {
        $table->id();
        $table->foreignUuid('affiliator_voucher_id')->constrained()->onUpdate('cascade')->onDelete('cascade');
        $table->string('unique_id')->unique()->nullable();
        $table->string('name')->nullable();
        $table->string('email')->nullable();
        $table->json('detail');
        $table->timestamps();
    });
}

排查与解决方案

  • 检查UUID大小写一致性
    数据库中affiliator_voucher_members.affiliator_voucher_id与affiliator_vouchers.id的UUID大小写可能存在差异,MySQL在utf8_bin等编码下字符串比较区分大小写,会导致关联失败。直接查询数据库对比两个字段的UUID值是否完全一致。

  • 明确模型主键类型
    在AffiliatorVoucher模型中添加protected $keyType = 'string';,Laravel默认主键类型为int,仅设置$incrementing = false未指定$keyType,可能导致查询时类型不匹配,引发部分关联失效。

  • 排查软删除影响
    AffiliatorVoucher使用了SoftDeletes,默认关联查询不会包含已软删除的记录。若关联的凭证被软删除,可修改关联方法加入withTrashed():

    public function voucher() :BelongsTo
    {
        return $this->belongsTo(AffiliatorVoucher::class, 'affiliator_voucher_id')->withTrashed();
    }
    

    或直接确认目标凭证未被软删除。

  • 查看实际执行的SQL
    开启查询日志,检查关联查询的SQL语句是否正确:

    DB::enableQueryLog();
    $member = \App\Models\AffiliatorVoucherMember::with('voucher')->find(172);
    dd(DB::getQueryLog());
    

    将生成的SQL直接在数据库中执行,验证是否能返回预期结果,定位SQL层面的问题。

  • 验证外键数据一致性
    执行SQL查询SELECT * FROM affiliator_vouchers WHERE id = (SELECT affiliator_voucher_id FROM affiliator_voucher_members WHERE id = 172),确认关联的凭证记录确实存在,排除数据不一致的情况。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.08 02:28:27