为多态数据透视表定义关系

问题描述 投票:0回答:1

我有这些模型:

  • 优惠
  • 报价报告
  • Vendor1Report
  • Vendor2Report
  • Vendor3Report

Offer表定义:

Schema::create('offers', function (Blueprint $table) {
    $table->id();
    $table->string('slug')->unique();
    $table->string('name')->nullable()->default(null);
    $table->timestamps();
});

OfferReport表定义:

Schema::create('offer_reports', function (Blueprint $table) {
    $table->id();
    $table->foreignIdFor(Offer::class)->constrained();
    $table->unsignedInteger('visitors_count')->default(0);
    $table->unsignedInteger('customers_count')->default(0);
    $table->unsignedInteger('sales_count')->default(0);
    $table->unsignedInteger('sales_amount')->default(0);
    $table->timestamp('starts_at')->nullable();
    $table->timestamp('ends_at')->nullable();
    $table->timestamps();
    $table->unique(['offer_id', 'starts_at', 'ends_at'], 'offer_report_range_unique');
});

每个供应商*报告表具有以下一般结构,具体结构因供应商而异:

Schema::create('vendor1_reports', function (Blueprint $table) {
    $table->id();
    $table->foreignIdFor(Offer::class)->constrained();

    // Column names are variable depending on vendor, but have some correlate on the OfferReport model.

    $table->timestamp('starts_at')->nullable();
    $table->timestamp('ends_at')->nullable();
    $table->timestamps();
    $table->unique(['offer_id', 'starts_at', 'ends_at'], 'offer_report_range_unique');
});

这是 OfferReportSource 数据透视表:

class OfferReportSource extends MorphPivot
{
    use HasFactory;

    protected $table = 'offer_report_sources';

    public function getMorphClass(): string
    {
        return 'offer_report_sources';
    }

    public function offerReport(): BelongsTo
    {
        return $this->belongsTo(OfferReport::class);
    }

    public function source(): MorphTo
    {
        return $this->morphTo();
    }
}

这是该枢轴的迁移:

Schema::create('offer_report_sources', function (Blueprint $table) {
    $table->id();
    $table->foreignIdFor(OfferReport::class)->constrained();
    $table->morphs('source'); // Vendor1Report, Vendor2Report, etc.
    $table->timestamps();
});

我尝试在 OfferReport 模型上创建这种关系:

public function sources(): MorphToMany
{
    return $this->morphToMany(
        OfferReportSource::class,
        'source',
        'offer_report_sources',
        'offer_report_id',
        'source_id'
    )->using(OfferReportSource::class);
}

当我尝试聚合时,我正在使用此查询来检查特定供应商报告是否已与特定日期范围内的组合 OfferReport 相关联:

OfferReport::where('offer_id', $vendorReport->offer_id)
    ->where('starts_at', '>=', $vendorReport->starts_at->startOfDay())
    ->where('ends_at', '<=', $vendorReport->ends_at->endOfDay())
    ->whereHas('sources', function (Builder $query) use ($vendorReport) {
        $query->where('source_type', $vendorReport->getMorphClass())
            ->where('source_id', $vendorReport->id);
    })
    ->firstOrNew();

这总是导致以下错误:

SQLSTATE[42000]: Syntax error or access violation: 1066 Not unique table/alias: 'offer_report_sources' (Connection: mysql, SQL: select * from `offer_reports` where `offer_id` = 31 and `starts_at` >= 2023-03-31 00:00:00 and `ends_at` <= 2023-03-31 23:59:59 and exists (select * from `offer_report_sources` inner join `offer_report_sources` on `offer_report_sources`.`id` = `offer_report_sources`.`source_id` where `offer_reports`.`id` = `offer_report_sources`.`offer_report_id` and `offer_report_sources`.`source_type` = offer_reports and `source_type` = vendor1_reports and `source_id` = 1) limit 1)

如果这是一条新记录,我会以特定方式为每个供应商编译所有数据,保存条目,然后我尝试将供应商报告附加到新的 OfferReport:

$offerReport->sources()->attach($vendorReport);

如果我尝试执行上面的附件(假设我只是跳过了

whereHas
检查的损坏的
firstOrNew
部分,那么我会收到此错误:

SQLSTATE[23000]: Integrity constraint violation: 1452 Cannot add or update a child row: a foreign key constraint fails (`webseeds`.`offer_report_sources`, CONSTRAINT `offer_report_sources_offer_report_id_foreign` FOREIGN KEY (`offer_report_id`) REFERENCES `offer_reports` (`id`)) (Connection: mysql, SQL: insert into `offer_report_sources` (`offer_report_id`, `source_id`, `source_type`) values (2, 10, offer_report_sources))

显然

offer_report_sources
根据查询错误出现在错误的地方,但我似乎无法弄清楚如何构建我的多态枢轴关系方法
source()
来处理这些可以作为部分引用的变量表名的多态性。

laravel eloquent pivot-table eloquent-relationship laravel-10
1个回答
0
投票

作为您的表结构,您不能在模型 OfferReport 中定义雄辩的关系来源。

在OfferReport中,可以对vendor1Report、Vendor2Report、Vendor3Report使用morphedByMany,如:

/**
  * Get all of the vendor1Report that are assigned this tag.
  */
 public function vendor1Report(): MorphToMany
 {
    return $this->morphedByMany(vendor1Report::class, 'source');
 }

参考:https://laravel.com/docs/10.x/eloquent-relationships#many-to-many-polymorphic-relations

© www.soinside.com 2019 - 2024. All rights reserved.