2017-01-17 3 views
2

При попытке повторного использования кода я написал в основном 14 лет назад. Я пришел к выводу, что прекрасная небольшая настройка, которую я написал тогда, была ... отсутствующая в определенных местах, а именно обработка пользовательских входов.PHP/MySQL лучше искать пользователя

Урок: Никогда не недооценивайте возможность пользователей загружать мусор, опечатки и обманывать мимо ваших валидаторов.

Старый способ достигает критической массы, поскольку в выпадающем списке SELECT есть 470 элементов. Я хочу переосмыслить эту часть процесса, поэтому мне не нужно беспокоиться о том, что она наносит удар.

Итак, идея заключается в создании метода нечеткого поиска, так что после того, как машинистка войдет в строку поиска, мы проверим против пяти частей данных, все из которых находятся в одной строке.

Мне нужно проверить имя, представленное в отношении имени этапа, двух также известных имен, а также их юридического имени и в качестве окончательной проверки индекса soundex() на основе их имени этапа (это несколько ошибок орфографии пропущено иначе)

Я пробовал сложный блок кода, чтобы проверить эти вещи (и это не работает, главным образом потому, что я думаю, что я закодировал слишком строгие сравнения) как часть цикла do/while ,

В приведенном ниже каталоге var $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 и передать идентификатор # в качестве значения для этих вариантов.

Thats, когда я нажимаю «Мне нужно использовать массив в задаче WHERE», и после обнаружения этого ответа, я начинаю подозревать, что мне не повезло из-за Stipulation # 2 ниже. Поэтому я начал искать альтернативные методы поиска, и я не уверен, что я где-то, но больше смущен.

Итак, есть ли лучший способ сканировать одну таблицу для шести полей, проверив пять против ввода пользователя и отметив шестой для отображения в подмножестве исходной таблицы?

процесс мысли:

Против всей таблицы, для каждой записи, тест $ Rin против этих тестов в таком порядке:

$ Рин -> сценическое имя
$ Rin -> AKA1
$ Rin -> AKA2
$ Rin ->
юридическое имя физического лица Саундэкс ($ Rin) -> SOUNDEX

, где удар по любому из пяти операций добавляет ID # в массив результатов, который используется для сужения результатов от 470 исполнителей до разумного списка на выбор.

УСЛОВИЙ:

1) Как написано, я знаю, что это уязвимы для атаки инъекции SQL.

2) Сервер запускает PHP 4.4.9 и MySQL 4.0.27-Standard, я не могу его обновить. Я должен доказать, что это работает, прежде чем деньги будут потрачены.

3) Это материал на уровне хобби, а не моя дневная работа.

4) Исполнители часто используют неанглийские имена или элементы в своих именах, и это привело к опечаткам и дублированию машинистами ввода данных.

Я нашел много ответов mysqli и PDO для такого рода вещей, и я вижу много вещей, которые только наполовину имеют смысл (например, ссылка № 4 ниже). Я работаю над тем, чтобы ускорить это, пытаясь исправить то, что сломалось.

мест уже смотрели:

  1. PHP mysql using an array in WHERE clause
  2. PHP/MySQL small-scale fuzzy search
  3. MySQL SubString Fuzzy Search
  4. Sophisticated Name Lookup
+0

Прежде всего, «mysql_ *» теперь дефферируются. Вместо этого используйте «mysqli_ *». :) – Ronald

+0

Является ли mysqli доступным на PHP v4.4.9? –

+1

Имея несколько сотен опций и тип-вперед, я предлагаю загружать данные через сервисный вызов (AJAX) в фоновом режиме после загрузки страницы и обрабатывать typeahead с помощью инструмента Javascript, например. [Twitter's Typeahead library] (https://twitter.github.io/typeahead.js/examples/), * особенно * если вы ищете несколько столбцов. – alttag

ответ

1

я упомянул в комментариях, что библиотека Javascript машинописный может быть хорошим выбор для вас. Я обнаружил, что Twitter's Typeahead и движок Bloodhound являются довольно надежными. К сожалению, документация представляет собой смешанную сумку: до тех пор, пока то, что вам нужно, очень похоже на их примеры, вы золотые, но некоторые детали (объяснения токенизаторов, например) отсутствуют.

В одном из several questions re Typeahead здесь на переполнение стека, @JensAKoch говорит:

Честно говоря, я думаю, что твиттер дал на typeahead.js. Мы смотрим на 13000 звезд, полный bugtracker без сопровождения и сломанное программное обеспечение, последний выпуск 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 "]"; 

стороне клиента код:

В этом примере используется static JSON file как заглушки для всех Результаты. Если вы ожидаете, что ваш результирующий набор пройдет более 1000 записей, вы должны посмотреть на remote option of 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>

Для простоты, здесь Gist of the client-side code.

+0

Это похоже на жизнеспособное решение. Я не так разбираюсь в javascript, как в PHP. Я непременно расскажу об этом. Спасибо. –

Смежные вопросы