Wyszukiwarka - zapytanie zależne od warunków

Często piszemy wyszukiwarki. Jaka ich rola? Banalnie prosta - na podstawie zadanych kryteriów znaleźć żądane informacje. W tym celu tworzymy zapytanie, które zawiera nasze kryteria wyszukiwania. Zadanie wydaje się proste, jednak wielu początkujących programistów ma z tym problem. Bo o ile potrafią napisać zapytanie, które składa się ze stałej liczby warunków, o tyle z zapytaniem ze zmienną liczbą warunków, uzależnioną od wpisanych wartości w formularzu, mają już problem. W artykule tym postaram się Wam pomóc w oswojeniu tego zagadnienia.

Algorytm tworzenia zapytania ze zmiennym warunkami jest w miarę prosty. Pokażę go na przykładzie kodu napisanego w pseudo php:

<?php
$wh = array(); //inicjalizujemy tablicę z warunkami
if ($warunek1) //jeśli spełniony jakiś warunek1
   $wh[] = 'jakiś warunek1'; //dodajemy warunek sql
if ($warunek2) //jesli spelniony jakis warunek2
   $wh[] = '(jakiś warunek2 or jakis warunek 3)'; //dodajemy jakis warunek sql
//..... i tak dalej

// jesli tablica warunków nie jest pusta, to tworzymy mysqlowy where, 
//który składa się z połączeń naszych warunków. 
//Warunki łączymy poprzez AND, gdyż tak zazwyczaj łączy się warunki przy wyszukiwarkach
if (!empty($wh))
   $where = 'where '.implode(' and ', $wh);
else
   $where = ''; //jesli nie było zadnych warunkow, to nasz where nie istnieje

//a teraz tworzymy nasze glowne zapytanie i łączymy je z naszymi warunkami
$sql = 'select * from tabela '.$where;

//a tutaj juz sobie wykonujemy normalnie zapytanie
?>

No, to teraz skoro znamy już algorytm, przystąpmy do prawdziwej sytuacji. Załóżmy, że mamy formularz na wpisanie imienia, nazwiska i przedziału wiekowego.

<form method="post">
Podaj imię: <input type="text" name="name" />
Podaj nazwisko: <input type="text" name="surname" />
Podaj wiek od: <input type="text" name="age_from" />
Podaj wiek do: <input type="text" name="age_to" />
</form>

A teraz tworzymy zapytanie uwzględniające te kryteria wyszukiwania. Zapytanie to nie będzie uwzględniało zabezpieczeń przed różnymi atakami typu SQLInjection - nie chcę zaciemniać kodu dodatkowymi "bajerami".

<?php
$wh = array(); //inicjalizujemy tablicę z warunkami
if (!empty($_POST['name'])) //jeśli podano imię
   $wh[] = "NAME = '$_POST[name]' "; 

if (!empty($_POST['surname'])) //jeśli podano nazwisko
   $wh[] = "SURNAME = '$_POST[surname]' "; 

if (!empty($_POST['age_from'])) //jeśli podano zakres dolny wieku
   $wh[] = "AGE >= $_POST[age_from]"; 

if (!empty($_POST['age_to'])) //jeśli podano zakres górny wieku
   $wh[] = "AGE <= $_POST[age_to]"; 

if (!empty($wh))
   $where = 'where '.implode(' and ', $wh);
else
   $where = '';

//a teraz tworzymy nasze glowne zapytanie i łączymy je z naszymi warunkami
$sql = 'select * from tabela '.$where;

?>

I już. Tym oto sposobem możemy tworzyć dowolną liczbę kryteriów dla naszej wyszukiwarki i w miarę prosty sposób nimi zarządzać. Zapewne gdy już nabierzecie doświadczenia, wymyślicie jakieś własne lepsze mechanizmy, ale na początek metoda ta wydaje się być jedną z lepszych.

ps: pamiętajcie, że w implode tam gdzie mamy ' and ' znajdują się dwie spacje: jedna przed and, a druga po and ( [spacja]and[spacja] ). Jest to niezbędna konstrukcja by otrzymać prawidłowo zbudowany warunki zapytania.

Komentarze

 

2011-05-16 16:19 gość_sesuo

Tak tylko czysto estetycznie. Jeśli nie będzie warunków, Twoje zapytanie będzie wyglądać mniej więcej tak:

"select * from tabela "

Spacja na końcu jest jak dla mnie odrobinę drażniąca. Drugą sprawą są dobre nawyki (nie chodzi tylko o ten przykład).

2011-05-17 07:20 nospor

Faktycznie niesamowity problem...
<?php
if (!empty($wh)) 
   $where = ' where '.implode(' and ', $wh); 
else 
   $where = ''; 

//a teraz tworzymy nasze glowne zapytanie i łączymy je z naszymi warunkami 
$sql = 'select * from tabela'.$where;

?>
i już spacja zniknęła. Taka spacja nie ma żadnego znaczenia, a jak tobie przeszkadza to naprawdę mogłeś sobie zmienić w 3 sekundy jak ja teraz

Co do dobrych nawyków to nie wiem o co ci chodzi

2012-06-21 13:21 gość_Greg

Hej. Bardzo fajnie wytłumaczone. Ale jak to wyświetlić teraz ? mamy formularz, mamy kod, a jak możemy to dynamicznie wyswietlić ??

2012-06-21 14:09 nospor

Nie za bardzo rozumiem w czym masz problem....
Masz zapytanie końcowe:
$sql = 'select * from tabela '.$where;
Nie potrafisz wykonać zapytania przy pomocy mysql_query i wyświetlić wyników przy pomocy mysql_fetch_array?

2012-07-03 12:26 gość_Crew

Jak to połączyć z full textem?

2012-07-03 12:53 nospor

I znowu nie kumam pytania. Jak to połączyć z full text? Normalnie. full text znasz?
Nie? No to się wpierw naucz fulltext
Tak? No to w czym problem? Zasada łączenia ta sama.

2012-07-21 12:51 gość_hikari

Ja mam problem z podawaniem dat. Korzystam z PostreSQL.

W moim formularzu podaję różne kryteria w tym dwie daty: data urodzenia i data wizyty.

Problem polega na tym, że jeśli nie podaję żadnej daty to wszystko jest ok i wyświetla mi wiersze tabel,
jeśli podaję obie daty też jest oki wyświetla mi wiersze
natomiast jeśli podam tylko jedną z możliwych dat pojawia się błąd:

Error in query:SET DATESTYLE TO 'European,SQL'; SELECT imie, nazwisko, data_urodzenia, miasto, ulica, nr_domu FROM pacjent INNER JOIN adres ON pacjent.adres = adres.id_adres INNER JOIN wizyta USING (id_pacjent) WHERE imie LIKE '%%' AND nazwisko LIKE '%%' AND data_urodzenia ='' AND data_wizyty ='15/06/2005' AND pesel LIKE '%%' AND ulica LIKE '%%' AND miasto LIKE '%%' ORDER BY nazwisko. BŁĄD: nieprawidłowa składnia wejścia dla typu date: "" LINE 8: AND data_urodzenia ='' ^

Jak ten problem rozwiązać?

2012-07-21 17:24 nospor

Z komunikatu błędu wynika, że podajesz date w nieprawidłowym formacie

2012-11-24 22:39 gość_wieczorny

No to średnio na jeża ta wyszukiwarka bo zawsze wykona się
SELECT * FROM tabela
czyli jak nie ustawisz pól to wypluje wszystkie rekordy.

można tak
http://forum.nospor.pl/programowanie/php/wyszukiwarka-mysql-koreya-ft49.html

2012-11-26 08:43 nospor

To że nie działa jak Ty chcesz, nie znaczy że działa średnio na jeża....
Dla mnie oczywistym jest, że jak nic nie wpisałeś w filtr, znaczy że chcesz wyniki wszystkiego. Dopiero filtr zawęża wyszukianie....

2014-03-17 18:37 gość_gurcik

Przydatny skrypt ale nożna go użyć w wyszukiwaniu rekordów z mysql po dacie tzn data_od, data_do?

2014-03-17 18:42 nospor

No a czemu nie? Czym sie rózni szukanie po data_od po szukania np. po NAME? Technicznie niczym.

2014-03-17 18:48 gość_gurcik

Tak też myślałem, ale po próbie wyskakuje mi mysql_num_rows()expects parameter 1 to be resource, boolean given in ...
Jestem jeszcze na poczatku drogi do poznania PHP i przyznam że to jest dla mnie problem :-(

2014-03-17 18:57 nospor

No to pewnie coś zepsules dodaje to pole. No skad mam wiedziec nie widzac kodu??
Poza tym wyswietl sobie blad zapytanie przy pomocy mysql_error()

2014-03-17 19:55 gość_gurcik

nospor - dzięki, pozbylem się bledu ale po wpisaniu przedziału czasu do data_od i data do sprawdziłem co sieznajduje w $where i where:data='2014-03-13' and data='2014-03-20' nie powinno być between zamiast and?

2014-03-18 08:11 nospor

Przeciez to masz robic dokladnie tak samo jak podalem w przykladzie age_from, age_to .....

2014-03-18 19:27 gość_gurcik

Popełniłem błąd w kodzie. Teraz wszystko śmiga. Jeszcze raz dzięki za pomoc.
Pozdrawiam

2014-03-20 14:55 gość_gurcik

Czy jest możliwość żeby 'name' albo 'surname' szukał z %'name'% . Jak to wkomponowac? Kombinuje i nie mogę wykombinowac

2014-03-20 16:04 nospor

Nie bardzo rozumiem w czym masz problem.... chcech miec % to dodaj. Kto broni?

2014-03-20 18:19 gość_gurcik

Nikt nie broni ale nie wiem w którym miejscu

2014-03-20 19:37 nospor

No to pokaz kod co probujesz zrobic, bo naprawde nie ogarniam z czym masz problem

2014-03-21 19:45 gość_gurcik

W przykładzie jest <?php
$wh = array(); //inicjalizujemy tablicę z warunkacałą if (!empty($_POST['name'])) //jeśli podano imię
   $wh[] = "name = '$_POST[name]' "; 

i inne wartości które ma pobrać z formularza. Chciałbym dodać % do name czyli %name% i próbowałem w taki sposób:
if (!empty($_POST['name'])) //jeśli podano imię
   $wh[] ="`name` =  '%$_POST[name]%' ";

ale nie działa. A może % ma być dodany gdzieś przy tworzeniu zapytania?

if (!empty($wh))
   $where = 'where '.implode(' and ', $wh);
else
   $where = '';

//a teraz tworzymy nasze glowne zapytanie i łączymy je z naszymi warunkami
$sql = 'select * from tabela '.$where;

?>
Ot cała zagwozdka

2014-03-21 19:49 nospor

Skoro uzywasz % to nie = a LIKE.... Powinienies to wiedziec, skoro wpadles na trop %

I na przyszlosc nie pisz "nie dziala" bo to nic nie mowi. Pisz czym sie objawia to nie dzialanie.

2014-03-23 19:09 gość_gurcik

No tak umknęło mi to LIKE. Dzięki

2015-01-20 13:12 gość_tenloginjestzajety

tego szukałem, dzięki

Dodaj komentarz

 

Dostępne bbcode: b, u, i, url, code, php, css, html, sql, js

Skrypty użytkowników

  1. Klasa obsługi szablo... Lirdoner
  2. Sekcje user76
  3. Klasa walidująca for... user76
  4. Licznik Gości online korey
  5. Form Builder Comandeer
  6. Dynamiczny licznik z... korey
  7. Captcha Comandeer