2014-10-15 4 views
0

В настоящее время я пытаюсь собрать довольно простую форму поиска - все флажки - но столкнулся с проблемами, сгруппировавшими запрос. Я могу вернуть результаты, если выбрано 1 место, 1 опыт или только 1 язык. Если я выберу комбинацию любых моих результатов, в лучшем случае пятнистые. Мое намерение состоит в том, чтобы вернуть все результаты для пользователей с:Построение лучшего поискового запроса php/mysql

experience a OR b OR c AND location a OR b OR b OR d AND languages a OR b AND approved 

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

Какой тип запроса я должен искать при попытке выполнить поиск по 20 + языкам, более 50 мест и нескольким другим требованиям? И как мне его строить? Я на правильном пути?

$adv_search_query = "SELECT 
users.*, general.*, languages.*, experience.* 
FROM users 
    LEFT OUTER JOIN languages ON users.user_id = languages.user_id 
    LEFT OUTER JOIN general ON users.user_id = general.user_id 
    LEFT OUTER JOIN experience ON users.user_id = experience.user_id 
WHERE ("; 

if(!empty($_POST['location'])) { 
    foreach($_POST['location'] as $location) { 
     $location_input = " general.neighborhood LIKE '%" . $location . "%' OR"; 
    } 
    $adv_search_query .= trim($location_input, 'OR'); 
    $adv_search_query .= ") "; 
} 

if(!empty($_POST['languages']) && !empty($_POST['location'])) { 
    $adv_search_query .= "AND ("; 
} 

if(!empty($_POST['languages'])) { 
    foreach($_POST['languages'] as $language) { 
     $language_input = " languages." . $language . " = 1 OR"; 
    } 
    $adv_search_query .= trim($language_input, 'OR'); 
    $adv_search_query .= ") "; 
} 

if(!empty($_POST['experience']) && !empty($_POST['location'])) { 
    $adv_search_query .= "AND ("; 
} 

if(!empty($_POST['experience'])) { 
    foreach($_POST['experience'] as $exp) { 
     $exp_input = " experience." . $exp . " = 1 OR"; 
    } 
    $adv_search_query .= trim($exp_input, 'OR'); 
    $adv_search_query .= ") "; 
} 

if (isset($_POST["approved"])) { 
    $approved = " users.approved = 1 OR"; 
} else { $approved = ""; } 

if (isset($_POST["pending"])) { 
    $pending = " users.approved = 2 OR"; 
} else { $pending = ""; } 

if (isset($_POST["incomplete"])) { 
    $incomplete = " users.approved = 0 OR"; 
} else { $incomplete = ""; } 

if(isset($_POST['approved']) || isset($_POST['pending']) || isset($_POST['incomplete'])) { 
    $status_input = "AND (" . $approved . " " . $pending . " " . $incomplete . ""; 
    $adv_search_query .= trim($status_input, 'OR'); 
    $adv_search_query .= ") "; 
} 

$adv_search_query .= "AND users.admin_level = 0"; 

Столы

table.users 
user_id first_name last_name admin_level user_approved 
1  nick   jones  0    1  
2  johnny  rocket  0    1  
3  sally  fields  0    2  

table.general 
user_id city  state  zip  neighborhood 
1  baltimore maryland 00125 hamsterdam 
2  lakeland maine  11542 treemont 
3  sonic  new york 11763 highville 

table.languages 
user_id french german italian spanish 
1  0  1  0  1 
2  0  0  1  1 
3  1  1  1  1 

table.experience 
user_id waldorf kumon homeschooling 
1  0  1  0 
2  0  0  1 
3  1  1  1 
+2

Начните использовать 'IN', а не' OR' (это упростит вашу жизнь) и не приведет к проблемам с запутанными запросами, смешавшими 'AND' и' OR' –

+0

Спасибо. Это все равно даст мне такие же дрянные результаты, хотя, если не будет другого использования, а не просто заменить OR. – Klav

ответ

1

Во-первых, следует знать, что ваш код чувствителен к SQL инъекции в:

general.neighborhood LIKE 

часть.

В этом типе здания SQL запроса, «массив()» и «взрывать» Ваши друзья:

$experience_valid_values = array('exp1', 'exp2'); 
$experience_conditions = array(); 
if(!empty($_POST['experience'])) { 
    foreach($_POST['experience'] as $exp) { 
     if (in_array($exp, $experience_valid_values)) { 
      $experience_conditions[] = 'experience.' . $exp . '=1'; 
     } 
    } 
} 

$language_valid_values = array('english', 'japanese', 'spanish', 'chinese'); 
$language_conditions = array(); 
if(!empty($_POST['language'])) { 
    foreach($_POST['languages'] as $language) { 
     if (in_array($language, $language_valid_values)) { 
      $language_conditions[] = 'language.' . $language . '=1'; 
     } 
    } 
} 

$conditions = array(); 
if (!empty($experience_conditions)) { 
    $conditions[] = '(' . implode(' OR ', $experience_conditions) . ')'; 
} 
if (!empty($language_conditions)) { 
    $conditions[] = '(' . implode(' OR ', $language_conditions) . ')'; 
} 

$sql = 'SELECT * 
     FROM users 
      LEFT OUTER JOIN experience ON users.user_id = experience.user_id 
      LEFT OUTER JOIN languages ON users.user_id = languages.user_id 
     WHERE 
     '; 
$sql .= implode(' AND ', $conditions); 

Использование «Array()» и «взрывать» сделает ваш код короче и проще читать. Это всего лишь короткий пример, на который я надеюсь, дадут вам эту идею.

+0

Ницца! Это довольно чисто. Благодарю. Я получу модификацию и посмотрю, как это получится. У вас были какие-то мысли в моем поиске по ключевым словам? Я уверен, что могу пойти с тем же методом, но '$ location_input =" general.neighborhood LIKE '% ". $. "% 'ИЛИ"; 'похоже, проблема – Klav

+1

Вы будете взорвать' general.neighborhood LIKE? ' и вам понадобится $ community_param_values ​​[] = '%'. $. '%'; Вам нужно создать подготовленное заявление из $ sql и передать $ neighbour_param_values ​​при его выполнении – gmarintes

+0

Сказали спасибо – Klav

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