PHP: Wyszukiwarka na stronÄ™

Dodano: 22 czerwca 2010 • 3387 wyÅ›wietleÅ„ • 1 komentarzy

media/upload/images/wyszukiwarki.[kacperkolodziej.com].1251179332.jpgW dzisiejszych czasach wyszukiwarka na stronie www jest już standardem. Nikt nie wyobraża sobie tego, że mógłby przeszukiwać ręcznie spisy treści czy mapy witryn. Wszystkiemu "winne" jest Web2. Kiedy treści tworzy się coraz prościej, robi to coraz więcej ludzi i bywa, że w jednym serwisie znajdujemy tysiące artykułów na różnorodne tematy. Wtedy dobra wyszukiwarka jest podstawą.

Nasza wyszukiwarka musi posiadać dobry algorytm wyszukiwania. Skrypt nie może być zbudowany tylko na podstawie jednego zapytania SQL, bo nie da to możliwości odpowiedniego posegregowania wyników. Dlatego napiszemy odpowiednią klasę, która będzie przeszukiwała bazę na podstawie różnych kryteriów, a następnie odpowiednio ułoży wyniki.

Baza danych

Do stworzenia wyszukiwarki będziemy potrzebowali tabeli w bazie danych. Załóżmy, że będzie to wyszukiwarka artykułów.

id int(11); Primary key; Auto increment
title varchar(255)
content text
author varchar(255)
date int(11)
views int(11)

Oto struktura potrzebnej tabeli (nazwijmy ją artykuly), na przykładnie której pokażę, jak napisać klasę wyszukiwarki.

Klasa PHP

Oto kod klasy:

<?php
class search {
	private $q;
	private $query, $sql;
	private $rpp, $page;
	private $results;
	
	public function __construct($q,$page=0,$rpp=10) {
		$this->q=addslashes($q);
		$this->query=null;
		$this->sql=null;
		$this->rpp=$rpp;
		$this->page=$page;
		settype($this->page,"integer");
		settype($this->rpp,"integer");
		if ($this->page<0) $this->page=0;
		$this->results=null;
	}
	
	public function Search() {
		$this->query[]="SELECT `id` FROM `artykuly` WHERE `title` LIKE '" . $this->q . "' ORDER BY `views` DESC, `title` ASC";
		$this->query[]="SELECT `id` FROM `artykuly` WHERE `title` LIKE '" . $this->q . "%' ORDER BY `views` DESC, `title` ASC";
		$this->query[]="SELECT `id` FROM `artykuly` WHERE `title` LIKE '%" . $this->q . "%' ORDER BY `views` DESC, `title` ASC";
		$this->query[]="SELECT `id` FROM `artykuly` WHERE `title` LIKE '%" . str_replace(" ","%",$this->q) . "%' ORDER BY `views` DESC, `title` ASC";
		$this->query[]="SELECT `id` FROM `artykuly` WHERE `content` LIKE '%" . str_replace(" ","%",$this->q) . "%' ORDER BY `views` DESC, `title` ASC";
		$this->query[]="SELECT `id` FROM `artykuly` WHERE `author` LIKE '" . $this->q . "' ORDER BY `views` DESC, `title` ASC";
		$this->query[]="SELECT `id` FROM `artykuly` WHERE `author` LIKE '%" . str_replace(" ","%",$this->q) . "%' ORDER BY `views` DESC, `title` ASC";
		foreach ($this->query as $query) {
			$this->sql[]=mysql_query($query);
			if (!$this->sql[(count($this->sql)-1)]) {
				$this->error[]="mysql error (Search function): " . mysql_error();
				return false;
			}
		}
		foreach ($this->sql as $sql) {
			while ($row=mysql_fetch_array($sql)) {
				$this->results[]=$row[0];
			}
		}
		$this->results=array_unique($this->results);
		return true;
	}
	
	public function printResults() {
		$doc=new DOMDocument("1.0","UTF-8");
		$doc->formatOutput=true;
		$table=$doc->appendChild($doc->createElement("table"));
		$table->setAttribute("class","searchResults");
		$start=$this->page*$this->rpp;
		$i=$start;
		$end=$i+$this->rpp;
		while ($i<$end) {
			$sql=mysql_query("SELECT `id`,`title`,`author` FROM `artykuly` WHERE `id` LIKE '" . $this->results[$i] . "' LIMIT 1");
			$row=mysql_fetch_array($sql);
			$tr=$table->appendChild($doc->createElement("tr"));
			if ($i%2==0) {
				$tr->setAttribute("class","p");
			} else {
				$tr->setAttribute("class","n");
			}
			$td1=$tr->appendChild($doc->createElement("td"));
			$link=$td1->appendChild($doc->createElement("a"));
			$link->setAttribute("href","/artykul.php?id=" . $row['id']);
			$anchor=$link->appendChild($doc->createTextNode($row['title']));
			$td2=$tr->appendChild($doc->createElement("td"));
			$authorLink=$td1->appendChild($doc->createElement("a"));
			$authorLink->setAttribute("href","/author.php?id=" . $row['author']);
			$authorAnchor=$authorLink->appendChild($doc->createTextNode($row['author']));
			$i++;
		}
		return $doc->saveXML();
	}
	
	public function pageButtons() {
		$pages=ceil(count($this->results)/$this->rpp);
		$doc=new DOMDocument("1.0","UTF-8");
		$doc->formatOutput=true;
		$form=$doc->appendChild($doc->createElement("form"));
		$form->setAttribute("action","/szukaj.php");
		$form->setAttribute("method","get");
		$q=$form->appendChild($doc->createElement("input"));
		$q->setAttribute("type","hidden");
		$q->setAttribute("name","q");
		$q->setAttribute("value",$this->q);
		$input=$doc->createElement("input");
		$input->setAttribute("type","text");
		$input->setAttribute("name","page");
		$input->setAttribute("value",$this->page+1);
		$input->setAttribute("size","3");
		$form->appendChild($doc->createTextNode("/" . $pages);
		$button=$form->appendChild($doc->createElement("input"));
		$button->setAttribute("type","submit");
		$button->setAttribute("value","idź");
		return $doc->saveXML();
	}
}
?>

Klasa zawiera 4 funkcje: __construct(), Search(), printResults() i pageButtons(). Niewtajemniczonym powiem, że pierwsza z nich, __construct(), jest uruchamiana przy tworzeniu kopii obiektu search:

$szukaj=new search(argumenty,funkcji,__construct);

Funkcja druga - Search(), Wykonuje zapytania do bazy, a następnie zwrócone wyniki (tylko id artykułów) zapisuje do tablicy $results, która następnie, dzięki funkcji array_unique() jest czyszczona ze z duplikowanych wpisów. Należy zauważyć, że zapytania do bazy są ułożone w takiej kolejności, że pierwsze zwraca wyniki, które są najbardziej odpowiednie dla wpisanego hasła, a ostatnie, te najmniej.

Kolejna funkcja - printResults() - przeszukuje za pomocą pętli while tablicę $results. W pętli wykonywane są zapytania do bazy MySQL, które mają za zadanie pobrać dane artykułu oznaczonego numerem id, który znajduje się na kolejnym miejscu w tablicy $results. Wyniki są grupowane według zmiennej $rpp (skrót z ang. results per page), która mówi, ile na jednej stronie ma znaleźć się wyników.

Ostatnia funkcja - pageButtons(), ma za zadanie dać użytkownikowi możliwość przejścia na inną stronę z wynikami. Tutaj jest to zrobione za pomocą formularza, do którego wpisuje się numer strony. Oczywiście nie jest to najlepszy sposób, ale z pewnością działający. Na razie wystarczy, a funkcję która będzie budowała lepszy system nawigacji po wynikach, napiszemy w kolejnej części artykułu, w której będziemy zajmować się także innymi udoskonaleniami.

Na koniec pokażę jak wykorzystać klasę.

<?php
$szukaj=new search($_GET['q'],$_GET['page']);
if ($szukaj->Search()) {
		print $szukaj->printResults();
} else {
		die('Wystąpił błąd!);
}
print $szukaj->pageButtons();
?>

Oczywiście skrypt należy odpowiednio "ubrać" za pomocą HTML i CSS. Ja powiem tylko, że należy dodać do arkusza CSS dwa wpisy:

tr.p {
background: #pierwszy_kolor;
}
tr.n {
background: #drugi_kolor;
}

Funkcja printResults() zawiera odpowiedni kod, który ma za zadanie nadawać w tabeli wierszom parzystym (które mają parzystą liczbę porządkową) klasę p, a nieparzystym klasę n. Taki mały dodatek z pewnością pomaga w orientacji w wynikach, szczególnie wtedy, kiedy tabela zawiera wiele kolumn z różnymi danymi.

Na dzisiaj to już koniec. Wkrótce napiszę kolejną część, w której opiszę jak udoskonalić naszą wyszukiwarkę nie tylko przez PHP, ale także JS i AJAX oraz bibliotekę JQuery.


Zobacz również:
Komentarze

marMozilla/5.0 (Windows; U; Windows NT 6.0; pl; rv:1.9.2.13) Gecko/20101203 BTRS28059 Firefox/3.6.13 ( .NET CLR 3.5.30729)

Hej,

A co z wyszukiwarką, która miałaby przeszukiwać tabelę w poszukiwaniu danej frazy, jeśli znalazłaby , pokazywała i podświetlała ?

13 lutego 2011 o 19:15:59

Napisz komentarz

Kacper KołodziejO mnie: Nazywam się Kacper Kołodziej. Jestem uczniem II klasy II LO w Pabianicach o profilu matematyczno-fizycznym. Od 7 lat gram na gitarze. Skończyłem Państwową Szkołę Muzyczną I stopnia w Pabianicach; aktualnie jestem w trzeciej klasie szkoły II stopnia. Oprócz muzyki zajmuję się także tworzeniem stron. Moje prace można obejrzeć w portfolio.

O blogu: Na tym blogu publikuję wszystkie artykuły mojego autorstwa dotyczące programowania, tworzenia stron www, komputerów i internetu, a także muzyki.



© by Kacper KoÅ‚odziej 2011 • Code powered by SpawnFramework v.1.5.1 - wersja zmodyfikowana