initialize(); $tagQuery = Db::name('qywx_external_contact_event')->alias('e'); MediaChannelService::applyExternalUserChannelFilter( $tagQuery, 'e.external_userid', [ 'source_tag_id' => 'tag-regression-id', 'source_tag_name' => '回归渠道', ] ); $tagSql = (string)$tagQuery->fetchSql()->select(); if (!str_contains($tagSql, 'qywx_external_contact_tag')) { throw new RuntimeException('tag 渠道未使用结构化客户标签关系表'); } if (!str_contains($tagSql, 'EXISTS (SELECT 1 FROM')) { throw new RuntimeException('tag 渠道未使用 EXISTS 半连接,避免物化整渠客户 ID'); } if (!str_contains($tagSql, 'channel_tag.external_userid = e.external_userid')) { throw new RuntimeException('tag 渠道未按事实表 external_userid 相关查询'); } if (!str_contains($tagSql, 'tag_id = ')) { throw new RuntimeException('单标签渠道应使用 tag_id = 走组合索引'); } if (str_contains($tagSql, 'tag_id IN (')) { throw new RuntimeException('单标签渠道不应退化为 tag_id IN'); } if (str_contains($tagSql, 'follow_users') || str_contains($tagSql, 'LIKE')) { throw new RuntimeException('tag 渠道仍在扫描 follow_users JSON'); } $legacyQuery = Db::name('order')->alias('o'); MediaChannelService::applyExternalUserChannelFilter( $legacyQuery, 'o.payer_external_userid', [ 'source_tag_id' => '', 'source_tag_name' => '仅名称老渠道', ] ); $legacySql = (string)$legacyQuery->fetchSql()->select(); if (!str_contains($legacySql, ' IN (SELECT channel_contact.external_userid')) { throw new RuntimeException('老渠道回退未使用去重 external_userid 子查询'); } if (!str_contains($legacySql, 'channel_contact.delete_time IS NULL')) { throw new RuntimeException('老渠道回退包含了已删除客户记录'); } $groupQuery = Db::name('qywx_external_contact_event')->alias('e'); MediaChannelService::applyExternalUserChannelFilter( $groupQuery, 'e.external_userid', [ 'source_tag_id' => '', 'source_tag_ids' => ['tag-group-a', 'tag-group-b'], 'channel_name' => '自媒体4', 'is_group' => true, ] ); $groupSql = (string)$groupQuery->fetchSql()->select(); if (!str_contains($groupSql, 'EXISTS (SELECT 1 FROM')) { throw new RuntimeException('分组渠道未使用 EXISTS 半连接'); } if (!str_contains($groupSql, 'tag_id IN (')) { throw new RuntimeException('分组渠道未按多个 tag_id 过滤'); } if (str_contains($groupSql, 'follow_users') || str_contains($groupSql, 'LIKE')) { throw new RuntimeException('分组渠道仍在扫描 follow_users JSON'); } $historicalQuery = Db::name('qywx_external_contact_event')->alias('e'); MediaChannelService::applyHistoricalExternalUserChannelFilter( $historicalQuery, 'e.external_userid', [ 'source_tag_id' => 'deleted-fan-channel-id', 'source_tag_name' => '已删粉丝渠道', ] ); $historicalSql = (string)$historicalQuery->fetchSql()->select(); if (!str_contains($historicalSql, 'historical_channel_contact.external_userid = e.external_userid')) { throw new RuntimeException('已删粉丝渠道未按 external_userid 关联历史客户快照'); } if (!str_contains($historicalSql, 'historical_channel_contact.follow_users LIKE')) { throw new RuntimeException('已删粉丝渠道未使用保留的 follow_users 快照'); } if (str_contains($historicalSql, 'historical_channel_contact.delete_time IS NULL')) { throw new RuntimeException('已删粉丝渠道错误排除了软删客户'); } echo "MEDIA_CHANNEL_EXTERNAL_USER_FILTER_OK\n";