您描述的问题实际上是哈希冲突。您有多个可能的输入值,并且您希望它们分解为一个明确的键。我在这里有几个想法。
正如@bishop 建议的那样,您真正需要确定的是任何给定的输入是否明确。不过,我的方法会略有不同:
对于任何给定的输入,我将生成所有可能匹配键的列表,并在数据库中查询整个列表。如果只返回一个结果,则没有问题,您可以根据该单条记录继续。ABCDE5
在这种情况下,用户是否输入或ABCDES
因为数据库中只有一个可能匹配任何一个都无关紧要。
但是,如果返回多个结果,您将无法确定用户的输入是否准确或输入错误。
(事后看来,最好将键设计成不可能出现任何模棱两可的字符对。例如,只允许“S”而不允许“5”,可以保证只有一个匹配项对于任何给定的输入,无论用户键入“S”还是“5”,因为您总是可以安全地将您在输入中看到的任何 5 转换为 S,因为知道它们是输入错误。事实上,根据确切的值,您可能会能够追溯修改数据库中的许多或所有键以遵循此规则并使查找不那么麻烦。)
无论如何,在那种模棱两可的情况下,我认为您别无选择,只能回推给用户并要求他们重新检查他们的输入,希望在屏幕消息中解释可能的问题。
编辑:
这是一个示例,用于根据用户实际提供的单个输入生成用户打算输入的可能值:
<?php
$inputs = [
'ABCDEF', // No ambiguity, DB should return 0 or 1 match.
'AAAAA1', // One ambiguous char, user could have meant `AAAAAI`
// instead so search DB for both.
'156ISG', // Worst case. If the DB values overlap a lot, there
// wouldn't be much hope of "guessing" what the user
// actually meant.
];
foreach ($inputs as $input) {
print_r(generatePossibleMatches($input));
}
//----------------------------------------
function generatePossibleMatches($input) {
$input = strtoupper($input);
$ambiguous = [
'I' => '1',
'G' => '6',
'S' => '5',
];
$possibles = [$input];
foreach ($ambiguous as $letter => $number) {
foreach ($possibles as $possible) {
foreach (str_split($possible) as $pos => $char) {
$addNumber = substr_replace($possible, $number, $pos, 1);
$addLetter = substr_replace($possible, $letter, $pos, 1);
if ($char === $letter && !in_array($addNumber, $possibles)) {
$possibles[] = $addNumber;
}
if ($char === $number && !in_array($addLetter, $possibles)) {
$possibles[] = $addLetter;
}
}
}
}
return $possibles;
}