如何移除两段重复的foreach循环以优化域名匹配逻辑?
优化域名匹配逻辑:移除重复循环的思路
原始代码
list($tld, $sld) = array_reverse(explode(".", $uri->getHost())); foreach ($arSiteDomains as $siteDomain) { list($siteTld, $siteSld) = array_reverse(explode(".", $siteDomain)); if ($sld == $siteSld) { $uri->setHost($siteDomain); break; } } foreach ($arSiteDomains as $siteDomain) { list($siteTld, $siteSld) = array_reverse(explode(".", $siteDomain)); if ($tld == $siteTld && $sld == $siteSld ) { $uri->setHost($siteDomain); break; } }
需求说明
当前域名存储在$uri->getHost()中,域名列表在$arSiteDomains数组内,需要找到最匹配的域名并设置,但不想保留两段重复的foreach循环,需要优化逻辑。
示例场景
$arSiteDomains = array( "en.example.com", "en.example.org", "lt.example.org", "lv.example.org", ); // 情况1:当前域名是example.net → 匹配en.example.com(SLD一致) // 情况2:当前域名是example.org → 匹配en.example.org(SLD+TLD都一致) // 情况3:当前域名是lv.example.net → 匹配lv.example.org(SLD一致)
优化思路1:单次循环内按优先级匹配
核心逻辑是在一次遍历中,先检查最严格的匹配规则(SLD+TLD完全一致),找到后直接跳出循环;如果没找到,就记录SLD一致的候选域名,循环结束后再使用候选。这样只需要遍历一次数组,避免重复循环。
$currentHost = $uri->getHost(); list($tld, $sld) = array_reverse(explode(".", $currentHost)); $matchedDomain = null; foreach ($arSiteDomains as $siteDomain) { list($siteTld, $siteSld) = array_reverse(explode(".", $siteDomain)); // 优先匹配SLD+TLD完全一致的域名(最高优先级) if ($sld === $siteSld && $tld === $siteTld) { $matchedDomain = $siteDomain; break; // 找到最优匹配,直接终止循环 } // 若还没找到最优匹配,记录第一个SLD一致的域名(次优先级) if ($matchedDomain === null && $sld === $siteSld) { $matchedDomain = $siteDomain; } } // 找到匹配项则设置域名 if ($matchedDomain !== null) { $uri->setHost($matchedDomain); }
优化思路2:预生成映射表快速查找
如果域名列表较大,这种方式更高效:先遍历一次数组,把域名拆解成SLD、TLD组合,生成两个映射表(精确匹配表和SLD匹配表),后续直接通过键查找,无需再次遍历数组。
$currentHost = $uri->getHost(); list($tld, $sld) = array_reverse(explode(".", $currentHost)); // 预生成匹配映射表 $fullMatchMap = []; // 键为"SLD.TLD",值为对应域名 $sldMatchMap = []; // 键为SLD,值为对应域名 foreach ($arSiteDomains as $siteDomain) { list($siteTld, $siteSld) = array_reverse(explode(".", $siteDomain)); $fullKey = "{$siteSld}.{$siteTld}"; $fullMatchMap[$fullKey] = $siteDomain; // 只记录第一个SLD匹配的域名,若需覆盖可去掉判断 if (!isset($sldMatchMap[$siteSld])) { $sldMatchMap[$siteSld] = $siteDomain; } } // 先尝试精确匹配,再尝试SLD匹配 $currentFullKey = "{$sld}.{$tld}"; if (isset($fullMatchMap[$currentFullKey])) { $uri->setHost($fullMatchMap[$currentFullKey]); } elseif (isset($sldMatchMap[$sld])) { $uri->setHost($sldMatchMap[$sld]); }
内容的提问来源于stack exchange,提问作者Viacheslav Ravdin
相关产品推荐
相关产品推荐

