В попытках омолодить код я написал в основном 14+ лет назад. Я пришел к выводу, что прекрасной маленькой установки, которую я написал тогда, не хватало в некоторых местах, а именно, для обработки пользовательских вводов.
УрокНикогда не стоит недооценивать способность пользователей вставлять мусор, опечатки и обманывать мимо ваших валидаторов.
Старый способ достигает критической массы, так как в выпадающем списке SELECT сейчас 470 предметов. Я хочу заново изобрести эту часть процесса, чтобы мне не пришлось беспокоиться о том, что она достигнет критической точки.
Таким образом, идея состоит в том, чтобы создать метод нечеткого поиска, чтобы после того, как машинистка вводила строку поиска, мы проверяли пять данных, каждый из которых находится в одной строке.
Мне нужно проверить имя, переданное по имени сцены, двум также известным именам, а также по их официальному имени и в качестве окончательной проверки по индексу soundex () на основе их имени сцены (при этом пропускается несколько пропущенных орфографических ошибок). иначе)
Я пробовал сложный блок кода, чтобы проверить эти вещи (и он не работает, главным образом потому, что я думаю, что я закодировал слишком строгие сравнения) как часть цикла do / while.
Внизу, вар $Rin
будет содержать предоставленное пользователем имя.
$setr = mysql_query("SELECT ID,StageName,AKA1,AKA2,LegalName,SoundEx FROM performers");
IF ($R = mysql_fetch_array($setr)) {
do {
$RT = substr(trim($Rin), 5);
$RT1 = substr($R[1], 5);
$RT2 = substr($R[2], 5);
$RT3 = substr($R[3], 5);
$RT4 = substr($R[4], 5);
$RTx = soundex($RT);
IF ($RT == $RT1) {
$RHits[] = $R[0];
}
IF ($RT == $RT2) {
$RHits[] = $R[0];
}
IF ($RT == $RT3) {
$RHits[] = $R[0];
}
IF ($RT == $RT4) {
$RHits[] = $R[0];
}
IF ($RTx == $R[5]) {
$RHits[] = $R[0];
}
} while ($R = mysql_fetch_array($setr));
}
Идея заключалась в том, что я создам массив ID # ближайших хитов, который я заполню в раскрывающемся списке выбора, который, как мы надеемся, будет иметь меньше посещений, чем вся таблица. Это означает, что запрашивается набор результатов из содержимого этого массива, чтобы отобразить имя исполнителя в раскрывающемся списке SELECT и передать ID # в качестве значения для этих вариантов выбора.
Вот когда я нажимаю кнопку «Мне нужно использовать массив в предложении WHERE», и после нахождения этого ответа я начинаю подозревать, что мне не повезло из-за пункта 2 ниже. Итак, я начал искать альтернативные методы поиска, и я не уверен, что я получил где-нибудь, но больше запутался.
Итак, есть ли лучший способ отсканировать одну таблицу для шести полей, проверяя пять по вводу пользователя и отмечая шестое для отображения в подмножестве исходной таблицы?
Мыслительный процесс:
Для всей таблицы, для каждой записи, тестируйте $ Rin с этими тестами в следующем порядке:
$ Rin -> StageName
$ Rin -> AKA1
$ Rin -> AKA2
$ Rin -> LegalName
soundex ($ Rin) -> SoundEx
где нажатие на любую из пяти операций добавляет ID # к массиву результатов, который используется для сужения результатов от 470 исполнителей до разумного списка для выбора.
УСЛОВИЯ:
1) Как я уже писал, я знаю, что это уязвимо для атаки SQL-инъекцией.
2) Сервер работает на PHP 4.4.9 и MySQL 4.0.27-Standard, я не могу его обновить. Я должен доказать, что это работает, прежде чем деньги будут потрачены.
3) Это хобби, а не моя повседневная работа.
4) Исполнители часто используют неанглийские имена или элементы в своих именах, и это привело к опечаткам и дублированию машинисток при вводе данных.
Я нашел много ответов mysqli и PDO для такого рода вещей, и я вижу много вещей, которые имеют смысл только наполовину (как ссылка № 4 ниже). Я работаю над тем, чтобы справиться с этими вещами, пытаясь починить то, что сломалось.
Места уже смотрели:
Я упомянул в комментариях, что библиотека типов Javascript может быть хорошим выбором для вас. Я обнаружил, что библиотека Typeahead и движок Bloodhound в Twitter довольно надежны. К сожалению, документация представляет собой смешанную сумку: пока то, что вам нужно, очень похоже на их примеры, вы золотые, но некоторые детали (например, объяснения токенизаторов) отсутствуют.
В одном из несколько вопросов о Typeahead здесь, на переполнении стека, @JensAKoch говорит:
Честно говоря, я думаю, что твиттер отказался от typeahead.js. Мы смотрим на 13000 звезд, полный багтрекер без сопровождающего и неработающего программного обеспечения, последний выпуск 2015 года. Думаю, это говорит само за себя или нет? … Итак, попробуйте одну из вилок: github.com/corejavascript/typeahead.js
Честно говоря, в краткой проверке документация на развилке выглядит немного лучше, если не сказать больше. Вы можете проверить это.
Применяются все предостережения об использовании старой версии PHP. Я настоятельно рекомендую переоборудование для использования PDO с PHP 5, но этот пример использует PHP 4 по запросу.
Полностью не проверенный код PHP. json_encode()
было бы лучше, но это не появится до PHP 5. Ваша конечная точка будет выглядеть примерно так:
headers("Content-Type: application/json");
$results = mysql_query(
"SELECT ID,StageName,AKA1,AKA2,LegalName,SoundEx FROM performers");
$fields = array("ID","StageName","AKA1","AKA2","LegalName","SoundEx");
echo "[";
$first = true;
while ($row = mysql_fetch_array($results)) {
($first) ? $first = false : echo ',';
echo "\n\t,{";
foreach($fields as $f) {
echo "\n\t\t\"{$f}\": \"".$row[$f]."\"";
}
echo "\n\t}";
}
echo "]";
В этом примере используется статический файл JSON как заглушка для всех результатов. Если вы ожидаете, что ваш набор результатов превысит 1000 записей, вам следует изучить remote
вариант Bloodhound. Это потребует от вас написания некоторого пользовательского кода PHP для обработки запроса, но он будет выглядеть в значительной степени аналогично конечной точке, которая сбрасывает все (или, по крайней мере, ваши самые распространенные) данные.
var actors = new Bloodhound({
// Each row is an object, not a single string, so we have to modify the
// default datum tokenizer. Pass in the list of object fields to be
// searchable.
datumTokenizer: Bloodhound.tokenizers.obj.nonword(
'StageName','AKA1','AKA2','LegalName','SoundEx'
),
queryTokenizer: Bloodhound.tokenizers.whitespace,
// URL points to a json file that contains an array of actor JSON objects
// Visit the link to see details
prefetch: 'https://gist.githubusercontent.com/tag/81e4450de8eca805f436b72e6d7d1274/raw/792b3376f63f89d86e10e78d387109f0ad7903fd/dummy_actors.json'
});
// passing in `null` for the `options` arguments will result in the default
// options being used
$('#prefetch .typeahead').typeahead(
{
highlight: true
},
{
name: 'actors',
source: actors,
templates: {
empty: "<div class=\"empty-message\">No matches found.</div>",
// This is simply a function that accepts an object.
// You may wish to consider Handlebars instead.
suggestion: function(obj) {
return '<div class="actorItem">'
+ '<span class="itemStageName">'+obj.StageName+"</span>"+ ', <em>legally</em> <span class="itemLegalName">'+obj.LegalName+"</span>"}
//suggestion: Handlebars.compile('<div><strong>{{value}}</strong> – {{year}}</div>')
},
display: "LegalName" // name of object key to display when selected
// Instead of display, you can use the 'displayKey' option too:
// displayKey: function(actor) {
// return actor.LegalName;
// }
});
/* These class names can me specified in the Typeahead options hash. I use the defaults here. */
.tt-suggestion {
border: 1px dotted gray;
padding: 4px;
min-width: 100px;
}
.tt-cursor {
background-color: rgb(255,253,189);
}
/* These classes are used in the suggestion template */
.itemStageName {
font-size: 110%;
}
.itemLegalName {
font-size: 110%;
color: rgb(51,42,206);
}
<script src="https://code.jquery.com/jquery-3.1.1.min.js"></script>
<script src="https://twitter.github.io/typeahead.js/releases/latest/typeahead.bundle.js"></script><p>Type something here. A good search term might be 'C'.</p>
<div id="prefetch">
<input class="typeahead" type="text" placeholder="Name">
</div>
Других решений пока нет …