Търсачка с много условия

vinsbg

Registered
Здравейте,

Опитвам се да направя една търсачка, която да взима (при нужда) няколко полета от които да търси.

Има едно поле, което търси в три колони: Title, Description и Keywords. Като допълнение може да се добавят още критерии от 2-3 падащи менюта. Та в момента имам това:
Код:
			if(isset($_POST["submit"])){
				$query = "";
				$tdkey = $_POST["tdkey"];
				$upload_program = $_POST["upload_program"];
				$upload_category = $_POST["upload_category"];
var_dump($upload_category);
				if(isset($tdkey)){ 
					$query = "SELECT * FROM document_upload WHERE upload_title LIKE '%$tdkey%' OR upload_description LIKE '%$tdkey%' OR upload_keywords LIKE '%$tdkey%'";				

		   			if(isset($upload_category)){ 
						$query .= "AND upload_category LIKE '%$upload_category%'";
					}
				   	if(isset($upload_program)){ 
						$query .= "AND upload_program LIKE '%$upload_program%'";
					}
				} else if (isset($upload_category)){ 
					$query = "SELECT * FROM document_upload WHERE upload_category LIKE '%$upload_category%'";
					
					if(isset($upload_program)){ 
						$query .= "AND upload_program LIKE '%$upload_program%'";
				  	}
				} else if (isset($upload_program)){ 
					$query = "SELECT * FROM document_upload WHERE upload_program LIKE '%$upload_program%'";
				} 
					$stmt = $pdo->prepare($query);
					//$stmt->bindValue(":search_title", "%" . $tdkey . "%");
					//$stmt->bindValue(":search_description", "%" . $tdkey . "%");
					//$stmt->bindValue(":search_keywords", "%" . $tdkey . "%");										
					//$stmt->bindValue(":search_category", "%" . $upload_category . "%");
					//$stmt->bindValue(":search_program", "%" . $upload_program . "%");
					
															
					$stmt->execute();								
					$result = $stmt->fetchAll();			
					if ($stmt->rowCount() > 0) { 
						echo '
							<table class="table table-bordered table-condensed"> 
								<thead>
									<tr>
										<th>ID</th>
										<th>Description</th>							
										<th>Keywords</th>
										<th>Category</th>
										<th>Program</th>
									</tr>
								</thead>';					
					
						foreach( $result as $row ) {
							echo '

								  <tbody>
								  <tr>			
									  <td>'.$row['upload_title'].'</td>
									  <td>'.$row['upload_description'].'</td>
									  <td>'.$row['upload_keywords'].'</td>
									  <td>'.$row['upload_category'].'</td>
									  <td>'.$row['upload_program'].'</td>
								  </tr>
								  </tbody>';
						}
						echo ' </table>';
					}
			}
При търсене в полето за title, description и keyword намира резултати. Проблема е когато търся само по upload_category и upload_program без да съм задал каквото и да е в полето за title, description и keyword ...

Би трябвало да пропусне първия IF и да отиде на ELSEIF-a, но не го прави и изкарва всичко, което има в таблицата...

+ че не съм много сигурен, чотва е правилния начин, но засега ще е така.. въпроса е да проработи.. после мога да я пооправя :)
 
Да не би да въвеждаш празен стринг и isset ти връща true, пробва ли със empty вместо isset?

Дай по едно echo във if-овете, за да провериш какво точно се случва.
 
lam3r4370 каза:
Да не би да въвеждаш празен стринг и isset ти връща true, пробва ли със empty вместо isset?

Дай по едно echo във if-овете, за да провериш какво точно се случва.
Прав си.. с if(!empty(....) стана. Изобщо не съобразих...
 
Само един допълнителен въпрос. В случая се очаква да има около 7 допълнителни полета, като идеята е да може всяко да се комбинира с всяко, че дори и по 2-3 на веднъж. Пример:

Избираш upload_program, избираш и upload_category, добавяш и още нещо и реално се получава да търси според 3 зададени критерия.

Това би означавало нещо от сорта на
Код:
if(!empty($tdkey)){ 
					$query = "SELECT * FROM document_upload WHERE upload_title LIKE '%$tdkey%' OR upload_description LIKE '%$tdkey%' OR upload_keywords LIKE '%$tdkey%'";				

		   			if(!empty($upload_category)){ 
						$query .= " AND upload_category LIKE '%$upload_category%' OR upload_category LIKE '%$all%'";
						
					}
				   	if(!empty($upload_program)){ 
						$query .= " AND upload_program LIKE '%$upload_program%' OR upload_program LIKE '%$all%'";
					}
				   	if(!empty($third)){ 
						$query .= " AND third LIKE '%$third%' OR third LIKE '%$all%'";
					}
...
Трябва и да се комбинират всичките 7-8 с всяко. Има ли някакъв по-разумен начин или просто трябва да си напиша всичките възможно комбинации, които ме касаят?
 
Да, с array ще стане, но само да питам първо - основната заявка
Код:
SELECT * FROM document_upload WHERE ...
си остава навсякъде, нали?
 
lam3r4370 каза:
Да, с array ще стане, но само да питам първо - основната заявка
Код:
SELECT * FROM document_upload WHERE ...
си остава навсякъде, нали?
Да, тя е основната и винаги ще си е тя...
 
Ако предположим, че полетата във БД и имената на input-ите са еднакви

Само си попълни $allowed array-а и оправи надолу кода, че да не е SQLi уязвим, но идеята е такава.

Код:
<?php
$allowed = array('upload_description',...);
$post = array_filter($_POST, function($field) {
return !empty($POST[$field]) && in_array($field, $allowed);
});
$query = '...';
foreach($post as $column=>$value) {
$query.=" AND $column LIKE '%$value%'";
}
 
Буташ си в един масив всичко разрешено:

PHP:
$fields = ['upload_program', 'something_else'];

В html-а го печаташ във формата на inputи със съответните имена:

Код:
foreach $fields as $field -> input name=$field

А заявката можеш да си я построиш така:

Код:
$query = 'SELECT * FROM table"
$query_param = '';
foreach $fields as $field
    if isset $_POST[$field]
        $query .= "or $field = ?'";
        $db_params[] = $field;
$query_param = substr($query_param, 3); //махаш първото or

db_execute_query($query . $query_param, $db_params); // трябва да подадеш сглобената заявка, а параметрите ще дойдат от масива db_params
 
lam3r4370 каза:
Код:
<?php
$allowed = array('upload_description',...);
$post = array_map($_POST, function($field) {
return !empty($POST[$field]) && in_array($field, $allowed);
});
$query = '...';
foreach($post as $column=>$value) {
$query.=" AND $column LIKE '%$value%'";
}
тогава $query би трябвало да е:
$query = 'SELECT * FROM document_upload ';
и във foreach-a
$query.=" WHERE $column LIKE '%$value%'";
$query.=" AND $column LIKE '%$value%'";

или се бъркам? WHERE клаузата малко ми бяга...
 
$query ти е
Код:
SELECT * FROM document_upload WHERE
и нататък имаш
Код:
$query.=" AND $column LIKE '%$value%'";
и само накрая, за да махнеш първия AND, вече извън foreach-а сложи

Код:
preg_replace('/AND/', '', $query, 1);
 
lam3r4370 каза:
$query ти е
Код:
SELECT * FROM document_upload WHERE
и нататък имаш
Код:
$query.=" AND $column LIKE '%$value%'";
и само накрая, за да махнеш първия AND, вече извън foreach-а сложи

Код:
preg_replace('/AND/', '', $query, 1);
Не мога да разбера в случая от къде се появява колоната след where и преди AND?
Сложих и това, но гърми с
Код:
Warning: array_map() expects parameter 1 to be a valid callback, array must have exactly two members....
Warning: Invalid argument supplied for foreach() in...
В момента цялото изглежда така:
Код:
			if(isset($_POST["submit"])){
				//$query = "";
				$tdkey = $_POST["tdkey"];
				$upload_program = $_POST["upload_program"];
				$upload_category = $_POST["upload_category"];
				$upload_subject = $_POST["upload_subject"];
				
				$upload_theme = $_POST["upload_theme"];				
				$upload_grade_level = $_POST["upload_grade_level"];
				$upload_difficulty_level = $_POST["upload_difficulty_level"];
				$upload_skills = $_POST["upload_skills"];
				$all = $_POST["all"];

$allowed = array('tdkey', 'upload_program', 'upload_category', 'upload_subject', 'upload_theme', 'upload_grade_level', 'upload_difficulty_level', 'upload_skills', 'all', 'upload_keywords' );
$post = array_map($_POST, function($field) {
return !empty($POST[$field]) && in_array($field, $allowed);
});
$query = 'SELECT * FROM document_upload ';
foreach($post as $column=>$value) {
$query.=" WHERE $column LIKE '%$value%'";
$query.=" AND $column LIKE '%$value%'";
}
 
Поправих го горе, но не си го видял, array_filter вместо array_map
А иначе заявката след основната си става
Код:
AND column LIKE ... AND column like ...
и просто махаш първото AND, за да стане валидна заявката

Т.е кода става

Код:
if(isset($_POST["submit"])){
$allowed = array('tdkey', 'upload_program', 'upload_category', 'upload_subject', 'upload_theme', 'upload_grade_level', 'upload_difficulty_level', 'upload_skills', 'all', 'upload_keywords' );
$post = array_filter($_POST, function($field) {
return !empty($POST[$field]) && in_array($field, $allowed);
});
$query = 'SELECT * FROM document_upload WHERE';
foreach($post as $column=>$value) {
$query.=" AND $column LIKE '%$value%'";
}
$query = preg_replace('/AND/', '', $query, 1);
 
Изкарва всичко от таблицата без значение, къде и какво съм въвел..
var_dump($query); изкарва
Код:
string(30) "SELECT * FROM document_upload "
 

Back
Горе