Shopware 6插件优化:邮箱黑名单通配符匹配与查询优化
优化方案
以下是修改后的代码,实现了一次性加载黑名单数据和通配符规则匹配的需求,同时避免了重复数据库查询:
use Monolog\Logger; use Shopware\Core\Framework\Context; use Shopware\Core\Framework\DataAbstractionLayer\EntityRepository; use Swa\ProductReviews\Components\LoggerHelper; use Shopware\Core\Framework\DataAbstractionLayer\Search\Criteria; class MailWithBlacklist { private EntityRepository $blacklistRepository; protected LoggerHelper $loggerHelper; // 类内缓存黑名单正则规则,避免重复查询数据库 private ?array $blacklistPatterns = null; public function __construct(EntityRepository $blacklistRepository, LoggerHelper $loggerHelper) { $this->blacklistRepository = $blacklistRepository; $this->loggerHelper = $loggerHelper; } /** * 检查邮箱是否在黑名单(支持通配符规则) * @param string $email * @param Context $context * @return bool */ public function isEmailBlacklisted(string $email, Context $context): bool { $patterns = $this->getBlacklistPatterns($context); // 遍历所有黑名单规则进行匹配 foreach ($patterns as $pattern) { if (preg_match($pattern, $email)) { $this->loggerHelper->addDirectRecord( Logger::DEBUG, 'Email matched blacklist rule', ['email' => $email, 'rule' => $pattern] ); return true; } } $this->loggerHelper->addDirectRecord( Logger::DEBUG, 'Email not found in blacklist', ['email' => $email] ); return false; } /** * 一次性加载黑名单数据并转换为正则匹配规则 * @param Context $context * @return array */ private function getBlacklistPatterns(Context $context): array { // 如果已有缓存,直接返回 if ($this->blacklistPatterns !== null) { return $this->blacklistPatterns; } // 从数据库获取所有黑名单规则(仅加载email字段,减少数据传输) $criteria = new Criteria(); $criteria->setFields(['email']); $blacklistEntries = $this->blacklistRepository->search($criteria, $context)->getEntities(); $patterns = []; foreach ($blacklistEntries as $entry) { $rule = $entry->getEmail(); if (empty($rule)) { continue; } // 将通配符规则转换为正则表达式: // 1. 转义正则特殊字符(如.、@) $regex = preg_quote($rule, '/'); // 2. 将*替换为正则的任意匹配符.* $regex = str_replace('\*', '.*', $regex); // 3. 添加首尾锚点,确保完整匹配邮箱,忽略大小写 $patterns[] = '/^' . $regex . '$/i'; } // 缓存规则 $this->blacklistPatterns = $patterns; return $patterns; } }
关键修改说明
一次性加载黑名单:
- 通过
getBlacklistPatterns方法一次性从数据库拉取所有黑名单规则,避免每次检查都发起查询。 - 使用类内属性
$blacklistPatterns缓存转换后的正则规则,重复调用时直接复用。
- 通过
通配符支持:
- 将黑名单中的
*通配符转换为正则表达式的.*(匹配任意字符),同时转义邮箱中的特殊正则字符(如.、@)。 - 采用忽略大小写的完整匹配(
^和$锚点),确保规则精准匹配邮箱格式。
- 将黑名单中的
性能优化:
- 查询时仅加载
email字段,减少数据库传输的数据量。 - 内存中遍历匹配,在批量检查场景(如50封邮件的定时任务)下,性能远优于多次数据库查询。
- 查询时仅加载
额外建议
如果需要支持黑名单规则的实时更新(如管理员修改黑名单后立即生效),可以:
- 移除类内缓存,每次调用
getBlacklistPatterns时重新拉取数据(适合实时性要求高的场景)。 - 集成Shopware的缓存组件(如Symfony Cache),设置合理的缓存过期时间,或在黑名单实体更新时触发缓存清除。
内容的提问来源于stack exchange,提问作者mlodhi
相关产品推荐
相关产品推荐

