internetul Windows Android

Bărbații au căutare php sf. Căutare sigură și ușoară în mySQL

JavaScript este blocat în browserul dvs. Vă rugăm să activați JavaScript pentru ca site-ul să funcționeze!

Căutarea site-ului luând în considerare morfologia limbii ruse în PHP + sitemap

În timp ce vă creați site-ul, vă veți gândi în cele din urmă la necesitatea de a face o căutare universală convenabilă pe acesta. Imediat există o soluție simplă: legarea căutării de la motoarele de căutare, de exemplu: căutare de la Yandex sau căutare de la Google. Dezavantajul general al unei astfel de soluții este că index de căutare vor exista doar acele pagini care sistem de căutare demn să adauge acolo. Cu alte cuvinte, o parte a site-ului dvs. nu va fi „căutată”.

Din păcate, să căutăm o altă soluție. Da, iată-l: Yandex.Server este un produs pentru căutarea pe site-ul dvs., luând în considerare morfologia limbii ruse. Se încarcă. În mediul Unix, Yandex.Server funcționează ca un daemon și pe platforma MS Windows, ca serviciu. Acestea. poate funcționa numai cu acces root la server. Când site-ul rulează pe găzduire partajată, nu este potrivit. :-( Al doilea dezavantaj este fără setări. Doar un singur buton „Start / Stop”.

Începem să „săpăm” internetul. Ei bine, cum este asta? Toată lumea are o căutare pe site-ul lor. Cumva oamenii o fac. De exemplu, există o soluție frontală pe care am descris-o demult: căutarea contextuală pe un site care nu ia în considerare declinarea cuvintelor și nu indexează cuvintele pe pagini. Dar cu cât aprofundezi mai mult sarcina, cu atât îți dai seama că sarcina nu este deloc banală.

Mai întâi, trebuie să scanați întregul site și să selectați toate cuvintele din acesta. Ei bine, știu deja cum - generatorul de sitemap face față cu succes acestei sarcini de mult timp.

În al doilea rând, trebuie să obțineți forma originală a tuturor cuvintelor. Există mai multe opțiuni aici, de exemplu, puteți utiliza streamer, care taie prefixul, sufixul și sfârșitul din cuvinte. Sau un sistem mai complex care folosește dicționare.

În al treilea rând, toate acestea trebuie încărcate în baza de date și indexate astfel încât căutarea să dureze un timp minim.

După ce am petrecut două săptămâni din timpul meu încercând un numar mare de a diferitelor opțiuni și algoritmi, m-am bazat pe următoarele:
1. Pentru scanare, folosesc un analizor simplificat, care, folosind o expresie regulată, decupează toate href-urile din pagină:

// Obțineți linkuri unice din pagina $ html = file_get_contents ($ url); if (preg_match ("| (.*?)

| sei ", $ html, $ arr)) ($ body = trim ($ arr); if (preg_match_all (" ~ ] * href = [""] ([^ ""] +) [""] [^<>] *> ~ si ", $ body, $ arr)) $ links = array_unique ($ arr);)

Acum trebuie să separăm legăturile externe de cele interne și să ne referim recursiv la analizorul cu adresa legăturii interne. Aici începe „rake” ... Legăturile interne pot fi specificate ca externe de la http: // domeniu / adresă, pot fi relative la pagina curentă, pot fi relative la eticheta de bază. Apoi, trebuie să verificați dacă indexarea acestei pagini în robots.txt este interzisă și dacă această pagină a fost deja accesată cu crawlere. Pentru a verifica, puteți utiliza exemplul de analiză robots.txt și exemplul de căutare SQL

$ cuvinte = preg_split ("/ [^ a-zA-Za-zaA-Z0-9] + /", $ body, -1, PREG_SPLIT_NO_EMPTY);

eliminați toate cuvintele scurte, convertiți toate cuvintele într-un caz și selectați baza (rădăcina) cuvântului. Pentru a izola rădăcina unui cuvânt, cel mai bine este să utilizați PHP, o clasă care vă permite să izolați rădăcinile cuvintelor luând în considerare morfologia rusă, engleză, ucraineană, estonă sau germană. Dicționarele pentru fiecare limbă durează 10-15 MB. În același timp, nu este nevoie să instalați software suplimentar pe server, totul va funcționa pe cea mai obișnuită găzduire. Dezavantajul este rata scăzută de extracție a rădăcinii. Biblioteca este conectată după cum urmează:

$ morphy = $ cale. "phpmorphy /"; require_once ($ morphy. "src / common.php"); $ opts = array ("storage" => PHPMORPHY_STORAGE_FILE, "predict_by_suffix" => true, "predict_by_db" => true, "graminfo_as_text" => true,); $ morphy = new phpMorphy ($ morphy. "dicts", "ru_RU", $ opts);

Obiectul phpMorphy are trei parametri:
prima este calea folderului dicționare;
a doua este pagina de cod „ru_RU” - rusă în utf-8, „rus” - rusă în windows-1251;
al treilea este opțiunile.

Opțiunile utilizează parametrul de stocare important, poate lua una din cele trei valori:

  • PHPMORPHY_STORAGE_FILE (nu încărcați complet fișierele de dicționar în memorie, aceasta este cea mai lentă opțiune, dar cea mai economică în ceea ce privește lucrul cu resursele serverului),
  • PHPMORPHY_STORAGE_SHM (încărcați întregul fișier de dicționar în memoria partajată, este necesară extensia PHP shmop) sau
  • PHPMORPHY_STORAGE_MEM (de asemenea, încărcați fișierul în memorie în întregime dacă shmop nu este utilizat, în ceea ce privește viteza nu este diferit de cel anterior).

Pe găzduirea partajată, cel mai probabil va trebui să utilizați prima opțiune, iar pe un server dedicat, pentru o viteză mai mare, este mai bine să utilizați opțiuni folosind memoria. Alegeți opțiunea pentru sarcinile dvs., dacă sunt planificate apeluri frecvente către modul, atunci este bine, desigur, să utilizați opțiunea cu memorie partajată.

Există un exemplu de funcționare a bibliotecii phpmorphy.

3. Acum trebuie să realizăm tabelele bazei de date în care vom stoca toate rezultatele scanării și analizei:

// lista paginilor site-ului sub formă de link, titlu și anunț // (primele 300 de caractere ale paginii care vor fi afișate în rezultatele căutării). CREAȚI TABELUL DACĂ NU EXISTĂ pagina (`id` int UNSIGNED NOT NULL PRIMARY KEY auto_increment,` url` varchar (255) not nul default "" UNIQUE, `title` varchar (128) not nul default" ",` description` text not null implicit "") // toate cuvintele site-ului. // cuvânt este ceea ce a rămas după stemmer (ceea ce am numit „rădăcină”) // sunetul este rezultatul funcției soundex pentru cuvântul dat. CREAȚI TABELUL DACĂ NU EXISTĂ cuvânt (`id` INT NESIGNAT NU NEGĂ CHEIE PRIMARĂ auto_increment,` cuvânt` varchar (30) nu nul, `sunet` char (4) nu nul implicit„ A000 ”) CREAȚI INDEX idx_word_word ACTIVAT”. $ Căutare -> cuvânt. " (word (8)) CREATE INDEX idx_word_sound ON ". $ search-> word." (sunet (4)) // Fiecare linie este un cuvânt „cuvânt” întâlnit pe pagina „pagină” „cnt” ori CREARE TABEL DACĂ NU EXISTĂ index (`pagină` int UNSIGNED nu nul,` word` int UNSIGNED nu nul, `cnt` SMALLINT UNSIGNED NOT NULL, UNIQUE (pagina, cuvânt))

Acum trebuie să realizăm un formular de interogare de expresie de căutare. Cea mai simplă formă de interogare de căutare arată astfel:

codul său este astfel:

Căutare:

Descărcați scriptul de căutare pe site

Mi-a luat foarte mult timp să creez acest exemplu, așa că vreau să îl convertesc în bani. Dacă vrei să-mi repete faza - noroc. Dacă îți prețuiești timpul, voi face schimb de timp cu bani. Pentru doar 2900 de ruble (~ 46 USD) veți primi un script de căutare complet deschis, detaliat comentat cu un generator de sitemap.

Arhivează conținutul:

  • phpmorphy / - o bibliotecă pentru extragerea rădăcinii cuvintelor
  • stemmer / - evidențiind tulpina unui cuvânt cu un algoritm rapid
  • config.php - setări pentru lucrul cu baza de date și funcții generale pe care este posibil să le utilizați deja și înlocuiți-le cu ale dvs.
  • index.php - formular de căutare + rezultate de căutare
  • install.php - creați tabele de baze de date MySQL pentru căutare
  • link_bar.php - navigare în pagină
  • search.php - clasa pentru lucrul cu căutarea. Conține metode:
    • sound_ex ($ string) - soundex rusesc pentru a obține sunetul unui cuvânt
    • update ($ url, $ scan = 0) - scanează recursiv toate paginile site-ului, evidențiază titlul paginii, corpul, descrierea.
    • ParsingWord ($ url, $ cuvinte) - analiza cuvintelor și adăugarea lor la baza de căutare
    • GetWords ($ cuvinte) - înlocuiește toate cuvintele cu rădăcinile lor în matricea trecută
    • url_short ($ url, $ base = "", $ ext = 0) - analiza link-ului, separarea externă de internă
    • is_robots ($ url) - verificați prezența unui link în robots.txt
    • ReadUrl ($ site) - citirea unei pagini de site folosind Curl, procesare, - redirecționări
  • sitemap.php - construiește un sitemap.xml sitemap
  • spider_http.php - site crawler bazat pe citirea și analizarea paginilor
  • spider_sitemap.php - site crawler bazat pe analiza sitemap.xml

Instructiuni de instalare:

  1. Despachetați conținutul arhivei search.zip în dosarul de căutare. Permiteți să scrieți din scripturi, setați drepturile la 777.
  2. Editați setările pentru utilizarea bazei de date în fișierul config.php Rulați install.php - vor fi create bazele de date necesare
  3. Rulați „/search/spider_http.php”, scanerul umple tabelele bazei de date:
    tabelul tuturor paginilor site-ului, conține titlu, cuvinte cheie și descriere.
    un tabel de cuvinte, rădăcinile cuvintelor găsite pe pagini cad în el
    Este posibil să formați o bază pe baza unui sitemap existent, pentru această utilizare "/search/spider_sitemap.php"
  4. Plasați interogarea de căutare pe pagini. Formular de interogare de căutare:
    Căutare:
  5. Editați formatul pentru afișarea rezultatelor pe pagina search.php
  6. rulați include_once "updater.php"; actualizare ($ url);
    când adăugați, modificați sau eliminați fiecare pagină
    $ url - pagina de actualizat.
    convenabil să apelați după salvarea modificărilor de pagină
    dacă pagina returnează o eroare 404 sau este goală, va fi eliminată din baza de date.
  7. rulați „/search/sitemap.php” pentru a genera sitemap.xml
    nu uitați să înregistrați calea către sitemap în robots.txt: sitemap: /search/sitemap.xml

Capabilități de script de căutare pe site

    Ceea ce scriptul nu poate:

  • nu se ia în calcul , rel = nofollow
  • textele obișnuite prezente pe toate paginile nu sunt eliminate din căutare

Acord de utilizare:

  • Puteți utiliza codul primit în oricare dintre dezvoltările dvs., nu vi se cere să furnizați un link către sursă.
  • NU aveți voie să îl revindeți, să-l plasați într-un produs gratuit sau acces limitatși, de asemenea, publica sub orice formă.
  • Toate celelalte drepturi sunt rezervate de autor.
  • Puteți contacta autorul cu întrebări, comentarii, urări. Contacte .

Atenție! Pentru 2900 de ruble (~ 46 USD) puteți alege una dintre cele două opțiuni de script care diferă semnificativ una de cealaltă.
Scriptul de căutare pentru un site în codificarea UTF-8 folosește funcțiile de lucru cu caractere cu doi octeți mb_ *, analizează paginile cu expresii regulate făcute pentru codificarea UTF-8 (unicod / Unicode), creează tabele de baze de date în utf-8.
Scriptul de căutare a site-ului în codificarea Windows-1251 folosește funcții pentru a lucra numai cu codificări str * cu un singur octet, analizează paginile cu expresii regulate făcute pentru codificări cu un singur octet.

Puteți intra sau înregistra! Sau fără înregistrare
Dând clic pe butonul de descărcare, sunteți de acord cu condițiile de utilizare a scriptului descrise pe această pagină.
O sumă de 2900 de ruble (~ 46 USD) va fi debitată din soldul dvs. și fișierul va fi descărcat.

Scurt ajutor privind implementarea căutării: procesarea șirurilor, tăierea caracterelor de serviciu, compunerea unei interogări în baza de date, logică, paginare, relevanță.

Partea 1: Declarații generale

Procesarea șirurilor

Primul pas este tăierea șirului cu mânere.

$ căutare = substr ($ căutare, 0, 64);

64 de caractere vor fi suficiente pentru ca utilizatorul să caute. Acum vom arde toate simbolurile „anormale” cu un fier de călcat roșu.

$ căutare = preg_replace ("/ [^ \ w \ x7F- \ xFF \ s] /", "", $ căutare);

În teorie, nu ar trebui să oferiți utilizatorului posibilitatea de a căuta cuvinte prea scurte - printre altele, acest lucru încarcă serverul. Deci, să căutăm doar cuvinte care sunt mai lungi de două litere (dacă limita este mai mare, înlocuiți „(1,2)„ cu „(1, numărul de caractere)”).

$ good = trim (preg_replace ("/ \ s (\ S (1,2)) \ s /", "", ereg_replace ("+", "", "$ search")));

Și după înlocuirea cuvintelor proaste, trebuie să comprimați spații duble (acestea au fost create special pentru căutarea corectă a cuvintelor scurte).

$ bun = ereg_eplace ("+", "", $ bun);

Să presupunem că dorim să oferim utilizatorului posibilitatea de a alege logica de căutare - să caute toate cuvintele sau doar unul dintre mai multe. Dacă doriți să faceți ca în Yandex - doi ampersanți înseamnă „ȘI” (cuvânt1 && cuvânt2 && cuvânt3) sau altceva, atunci nu sunt consilier. Șamanismul cu corzi pe un mic site imho nu merită timpul. Prin urmare, desenăm formularul de căutare după cum urmează:

Și în scriptul de căutare, verificăm încă o dată dacă utilizatorul a introdus:

Dacă (($ logic! = "AND") && ($ logic! = "OR"))
$ logic = "SAU";

Cum va fi utilizată logica este mai jos.

Căutați statistici

Ar fi bine să informați imediat utilizatorul câte rânduri a găsit în tabel. Pentru aceasta, se face o cerere suplimentară către baza de date:

$ query = "SELECT ID FROM table WHERE field LIKE"% ". str_replace (" ","% "SAU field LIKE"% ", $ good)."% "";

Pentru statistici despre cuvinte individuale, puteți face următoarele:

$ cuvânt = exploda ("", $ căutare); while (list ($ k, $ v) = each ($ word)) (if (strlen ($ v)> 2) $ stat = "$ v:". mysql_num_rows (mysql_query ("SELECT ID FROM table WHERE field LIKE" % $ v% "")); else $ stat = "$ v: un scurt";); $ word_stats =" Statistica cuvintelor: ". implode (" ", $ stat)."
"; unset ($ stat);

Paginarea rezultatelor

Ei bine, odată ce avem aspectul căutării și numărul de rânduri de rezultate ale căutării, efectuarea unei căutări pagină cu pagină este o bucată de tort. Verificăm variabila $ page (nu mai puțin de 0, nu mai mult de $ results_amount / $ rows_in_page). În interogarea care contează numărul de rânduri (vezi mai sus), scriem câmpurile și câmpurile pe care trebuie să le sortăm. Și apoi adăugăm

If ($ page == 0) $ request. = "LIMIT $ rânduri_în_pagină"; else $ request. = "LIMIT". $ pagină * $ rânduri_în_pagină. ",". $ rows_in_page;

(sintaxă: LIMIT<кол-во строк>sau LIMIT<кол-во строк отступа>, <кол-во строк>)

Ca urmare a executării unei astfel de interogări, vom obține exact aceleași linii care ar trebui afișate pe pagină. Pentru navigare, puteți fie să desenați linkuri către paginile următoare și anterioare, fie, mai dificil, să faceți o bară de navigare pe mai multe pagini.

Dacă ($ pagină> 0) tipăriți (" Pagina precedentă"); if ($ pagină<$results_amount/$rows_in_page) print ("Pagina următoare");

Lumina de fundal

Pentru a evidenția cuvintele de căutare din text cu caractere ușoare sau aldine, trebuie doar să faceți următoarele:

$ highlight = str_replace ("", "|", $ bun);

Spații (și le avem una câte una între cuvinte și nu există spațiu dublu nicăieri, în plus, le tăiem și de la capetele liniei), este suficient să o înlocuim cu o bară verticală - separatorul de opțiuni în expresii regulate. Nu evidențiem cuvintele „rele”, pentru că nu le căutăm în baza de date :). În codul care afișează textul, scrieți:

$ rând ["text"] = ereg_replace ($ evidențiere, " \\0", $ rând [" text "]);

După ce am scris numărul, m-am grăbit, a fost, să-mi scriu eu însumi un „punct culminant”. Nu a fost așa! Am etichete HTML în textul meu, așa că a trebuit să mă gândesc mult ... Sa dovedit așa (există o linie cu cuvinte pentru evidențiere):

$ text = eregi_replace ("> ([^<]*)($words)", ">\\1\\2", $ text);

Trebuie să te uiți pentru a vedea dacă acest cuvânt este în etichetă. Cu toate acestea, există o problemă cu intensitatea resurselor unui astfel de înlocuitor (K6-266 meu a gândit timp de șapte secunde peste un text de 5 kilobyte). Este trist.

Aplicând astfel de tehnici, puteți, în primul rând, să limitați libertatea de acțiune a utilizatorului și să îl împiedicați să a) să cunoască structura programului site-ului b) să suprasolicite serverul (de exemplu, prin trimiterea unui megabyte de text format din cuvinte (fraza s-a dovedit a fi ambiguă, dar rescrie nu o voi :) astfel încât scriptul să urce în baza de date de 250 de mii de ori) c) vezi un mesaj de eroare ca urmare a introducerii caracterelor speciale în limba interogării în șir. În al doilea rând, o oarecare comoditate pentru utilizator - paginarea și evidențierea.

Îmi amintesc că în articolul „Căutare sigură și comodă” era o astfel de frază

Partea 2. Relevanță dintr-o privire

Oleg Yusov

Pentru a afișa rezultatele căutării după relevanță, trebuie să:

  • Câmpurile obligatorii VARCHAR sau oricare dintre varietățile de câmpuri TEXT (SMALLTEXT, MEDIUMTEXT etc.), fac cheile FULLTEXT:

    TABEL ALTER TABLE ADAUGĂ FULLTEXT (câmp)

  • Mai departe - chiar mai ușor:

    $ query = "SELECT *, câmp MATCH AGAINST (" $ căutare ") ca relevant DIN TABEL ORDER BY relev DESC"

Note:

  • Implicit este să căutați cuvinte care conțin cel puțin 4 caractere. Acesta este corectat prin setarea #define MIN_WORD_LEN 4 în sursa ft_static.c, deși în opinia mea nu este necesar să o editați.
  • Simbolurile% din fraza de căutare nu sunt disponibile, cuvintele din fraza de căutare sunt analizate folosind o listă de delimitatori.
  • Lista delimitatorilor de cuvinte este editată în sursa ft_static.c.
  • Aveți nevoie de cel puțin o duzină de înregistrări în tabel pentru a începe să calculați relevanța.
  • Câmpul relev nu poate fi utilizat în clauza WHERE:

    SELECT *, câmp MATCH ÎMPOTRIVA ("$ căutare") ca relevant DIN tabel UNDE relev> 0 COMANDĂ PE relev DESC

    deși puteți:

    SELECT *, câmp MATCH AGAINST ("$ căutare") ca relevant DIN tabela UNDE câmp MATCH AGAINST ("$ căutare")> 0 COMANDĂ DE relev DESC

  • Viteza este destul de mare - chiar și în unele cazuri mai rapidă, cum ar fi căutarea
  • Toate cele de mai sus funcționează de la MySQL 3.23.23

Când creați indici FULLTEXT pe mai multe câmpuri, sunt posibile 2 opțiuni:

CREATE TABLE table (field1 VARCHAR (255), field2 TEXT, FULLTEXT (field1, field2)) CREATE TABLE table (field1 VARCHAR (255), field2 TEXT, FULLTEXT (field1), FULLTEXT (field2))

În primul caz, este posibilă o cerere:

SELECT *, MATCH câmp 1, câmp 2 ÎMPOTRIVA ("$ căutare") ca relevante DIN tabel ORDINĂ DE relev DESC

relevanța este calculată pentru toate câmpurile simultan. În al doilea caz, o astfel de cerere va genera o eroare. Aici calculăm relevanța după cum urmează:

SELECT *, MATCH câmp 1 ÎMPOTRIVA ("$ căutare") + MATCH câmp 2 ÎMPOTRIVA ("$ căutare") ca relevant DIN tabel ORDINĂ după relev DESC

A doua opțiune este oarecum mai complicată în interogări, cu toate acestea, în opinia mea, este mai bună, deoarece flexibilitatea căutării crește - pentru fiecare dintre câmpuri puteți seta, de exemplu, un coeficient de semnificație și, la însumarea relevanțelor câmpurilor, înmulțiți-le cu acest coeficient Fraza de căutare va fi căutată „mai mult” în câmpurile cu un coeficient ridicat. De exemplu, dacă efectuăm o căutare pe pagini indexate din catalogul de resurse, atunci câmpul cu numele paginii este de obicei specificat cu un coeficient mai mare decât câmpurile metaetichetelor de descriere sau cuvintelor cheie.

Partea 3: Exerciții cu relevanță

În primul rând, cum să adăugați un index FULLTEXT:

Mysql> alter table articlea add fulltext (ztext); EROARE 1073: coloana BLOB „ztext” nu poate fi utilizată în specificațiile cheii cu tipul de tabel folosit mysql> alter table articlea type = myisam; Interogare OK, 36 rânduri afectate (0,60 sec) Înregistrări: 36 Duplicate: 0 Avertismente: 0 mysql > alter table articlea add fulltext (ztext); Interogare OK, 36 rânduri afectate (10.00 sec) Înregistrări: 36 Duplicate: 0 Avertismente: 0

Indexurile textului se pot face numai pe tabele precum MyISAM. Textele sunt preluate din tabel și aruncate în fișierul index, iar volumul bazei de date crește. Despre cereri. Câmpul relev nu poate fi utilizat în clauza WHERE:

SELECT *, câmp MATCH ÎMPOTRIVA ("$ căutare") ca relevant DIN tabel UNDE relev> 0 COMANDĂ PE relev DESC

Deși puteți:

SELECT *, câmp MATCH AGAINST ("$ căutare") ca relevant DIN tabela UNDE câmp MATCH AGAINST ("$ căutare")> 0 COMANDĂ DE relev DESC

Un câmp calculat, desigur, nu poate fi utilizat într-un WHERE de toate regulile de sintaxă, dar poate fi utilizat într-un AVÂND:

SELECT *, câmpul MATCH ÎMPOTRIVA ("$ searchwords") ca relevant DIN TABELUL CARE are relevanță> 0 ORDINE BY relev DESC

Căutarea prin MATCH, așa cum a scris Oleg, se face doar pentru întregul cuvânt. ... Cu toate acestea, puteți să sortați numai după relevanță și să selectați după LIKE (acest lucru, desigur, va afecta performanța, nici nu știu cât).

Eliminăm condiția „relevanță> 0” și părăsim sortarea. Restul, ca înainte - tăiem șirul rezultat și îl transformăm într-o interogare cu mai mulți operatori LIKE:

SELECT *, CÂȘTIGURI câmp AGAINST ("$ căutare") CA relevante DIN tabel UNDE câmp CA LUCRĂ "% $ cuvânt1%" SAU câmp LIKE "% $ cuvânt2%" COMANDĂ DE DESC relevant, datefield DESC

Partea 4: Continuați ceea ce ați început

Continuăm subiectul căutării cu sortare după relevanță în baza de date MySQL, care a fost începută în septembrie.

MySQL sugerează utilizarea indexării FULLTEXT și a câmpului MATCH AGAINST pentru căutări de text integral în versiunile recente ale bazei de date. Cu toate acestea, nu toate serverele au ultima versiune MySQL și nu toți furnizorii de hosting vor să actualizeze software-ul din motive de fiabilitate a sistemului.

La un moment dat, am presupus că o căutare cu sortare după relevanță ar trebui făcută în mai multe interogări și, prin urmare, ar fi mai bine să nu o faceți deloc. Gândurile că relevanța pot fi luate în considerare în interogarea însăși m-au vizitat de la distanță, dar mi-a fost frică să prezint o astfel de construcție.

Cu toate acestea, un angajat al uneia dintre firmele de construcții de site-uri N-ska mi-a lăudat sistemul de căutare pe care îl folosesc pe site-urile lor. Nu mi-am amintit cererea cu siguranță, voi încerca să o reproduc astfel:

SELECȚIAȚI titlul, data_format (material_date, "% e.% C.% Y") AS date1, IF (text ca "% word1 word2 word3%", 3 * 10, 0) + IF (text LIKE "% word1%", 9, 0) + IF (text LIKE "% word2%", 9, 0) + IF (text LIKE "% word3%", 9, 0) CA relevanță DIN tabel UNDE text LIKE "% word1%" SAU text LIKE " % word2% "SAU text ca LIKE"% word3% "COMANDĂ PE relevanță DESC, material_date DESC

Arată îngrozitor, dar funcționează chiar și pe versiunile MySQL mai vechi. Am încercat să compar viteza de lucru cu această solicitare:

SELECȚIAȚI titlul, data_format (material_date, "% e.% C.% Y") AS date1, MATCH text CONTRA ("word1 word2 word3") AS relevance FROM table WHERE text LIKE "% word1%" OR text LIKE "% word2% „SAU text LIKE”% word3% „COMANDĂ PE relevanță DESC, material_date DESC

În medie, viteza unei interogări generice este la jumătate din cea a unei interogări care utilizează modele noi. Ceea ce este destul de logic - cu cât este mai versatilă, cu atât este mai mare intensitatea resurselor.

Să încercăm să construim automat o astfel de interogare. Tăiați linia lungă, precum și toate caracterele greșite și cuvintele scurte. Tragem o cerere.

$ query = "SELECT title, date_format (material_date,"% e.% c.% y ") AS date1, IF (text ca"% ". $ good_words."% ",". (substr_count ($ good_words, "" ) + 1). "* 10, 0) + IF (text LIKE"% ". Str_replace (" ","% ", 9, 0) + IF (text LIKE"% ", $ good_words)."% ", 9, 0) CA relevanță DIN TABEL UNDE text COME "%". Str_replace ("", "%" SAU text CA CA "%", $ good_words). "%" COMANDĂ PE relevanță DESC, material_date DESC ";

Nu foarte greu. Pentru fiabilitate și protecție împotriva inundațiilor, puteți limita numărul de cuvinte dintr-o interogare.

Câteva adăugiri la publicațiile anterioare

Numărul total de rânduri găsite în tabel. Pentru a afișa rezultatele căutării, desigur, trebuie să utilizați operatorul LIMIT (pentru a nu scrie de fiecare dată formarea acestui parametru, utilizați funcții gata făcute). Dacă nu se efectuează operațiuni de grupare în interogare, este mai bine să numărați numărul de rânduri imediat în interogare - COUNT (*) și nu după funcția php mysql_num_rows (). Puteți verifica mesele mari. Dacă este produs operațiuni de grup, facem o cerere cu COUNT (DISTINCT (<поле, по которому группируем>)), dar fără GROUP BY.

Lumina de fundal. Dacă nu există etichete html în texte, viața este mai ușoară

$ text = preg_replace ("/ word1 | word2 | word3 / i", " \\0", $ text);

Dacă etichetele sunt folosite în text, adică există trei opțiuni a) nu evidențiați b) deoarece utilizatorul nu vede etichetele (dacă nu este un utilizator foarte curios), atunci puteți crea un câmp index în care va fi fără etichete și caracterele [^ \ w \ x7F- \ xFF \ s] vor fi înlocuite cu spații (acestea sunt caracterele care sunt tăiate din șirul de căutare chiar de la început, deci nu se efectuează nicio căutare pe ele). În acest caz, căutarea și evidențierea trebuie făcute de index. c) faceți evidențierea textului dintr-un câmp obișnuit, după ce ați tăiat anterior etichetele cu funcția srip_tags ().

Versiunea completa codul de căutare, ca întotdeauna, în lista de fișiere.




Dacă mai aveți întrebări sau ceva nu este clar - bine ați venit la
11,1K

Una dintre cele mai populare și necesare funcții de pe orice site este o căutare implementată folosind un formular special. Această funcționalitate permite vizitatorilor să găsească rapid conținut care îi interesează pe site.

Astăzi vrem să vă spunem cum să faceți o căutare pe site folosind un formular special care va interoga tabelele bazei de date și va afișa informații despre managerii actuali de pe site. Veți învăța cum să creați tabele de baze de date care vor conține informații despre personalul actual.

Elaborați formulare de căutare când Ajutor PHPși, de asemenea, familiarizați-vă cu SQL ( Limbaj de interogare structurat) - un limbaj special pentru colectarea, înregistrarea și modificarea informațiilor conținute în bazele de date. Înainte de a începe, vă recomandăm să vă descărcați fișiere de proiect.

De ce ai nevoie

  • Instrument pentru lucrul cu bazele de date MySQL.
  • Server local sau la distanță cu suport PHP.
  • Editor de text.

Creăm o bază de date

Dacă nu sunteți pe deplin sigur că puteți afla baza de date a gazdei dvs., contactați furnizorul de găzduire pentru instrucțiuni sau asistență adecvate. După crearea bazei de date, va trebui să o conectați, să creați un tabel și să scrieți datele necesare.

Cel mai popular instrument de gestionare MySQL este PHP My Admin. Acest instrument va fi suficient pentru tutorialul nostru de astăzi.

Crearea unui tabel

Tabelul nostru trebuie creat în următorul format:

Nume coloană Tipul de date Lungime Nul sau Nu Nul Cheia principala? Increment auto
ID INT 1 Nu nul da da
Nume Varchar 50 Nu nul Nu. Nu.
Numele de familie Varchar 50 Nu nul Nu. Nu.
E-mail Varchar 50 Nu nul Nu. Nu.
Numar de telefon Varchar 15 Nu nul Nu. Nu.

Un tabel de baze de date este compus din coloane și rânduri, la fel ca în Excel. Prima coloană vă permite să identificați datele după nume. Urmează coloana Tipuri de date, care ne indică tipul de date conținute în coloană. Câmpul Lungime specifică cantitatea maximă de memorie (stocare) pentru o coloană de tabel. Folosim variabile care oferă mai multă flexibilitate. Cu alte cuvinte, dacă lungimea numelui complet este mai mică de 50 de caractere, atunci doar o parte din spațiul alocat va fi ocupat.

Și printre datele despre personal nu pot exista valori goale ( nul, gol). Primul rând este evidențiat în galben, deoarece coloana ID este cheia noastră principală. Cheia principală din baza de date asigură faptul că fiecare înregistrare este unică. Această coloană este, de asemenea, incrementată automat, ceea ce înseamnă că fiecare înregistrare din baza noastră de date va fi atribuită număr unic automat.

Intrăm în masă reprezentanții personalului

Odată ce ați înțeles tabelul, începeți să-l completați cu date. 6 intrări sunt suficiente pentru a remedia procedura în mintea ta. Mai jos este propriul meu exemplu:

Codul coloanei Nume Numele de familie E-mail Numar de telefon
2 Ryan Majordom 417-854-8547
3 Brent Callahan 417-854-6587

Proiectarea formularului

Pentru a crea un formular de căutare pe site prin Google, deschideți orice opțiune potrivită editor de text... Vă recomand să utilizați PSPad-ul gratuit. Puteți utiliza orice editor de text care oferă evidențierea sintaxei. Acest lucru va facilita foarte mult procesul de scriere și depanare a codului PHP. Când creați o pagină pentru formularul de căutare, asigurați-vă că o salvați în format .php, altfel codul PHP nu va fi analizat așa cum era de așteptat. După ce salvați documentul, copiați următorul marcaj în el:

Căutați contacte:

Căutare detaliată a contactelor

Puteți căuta după nume sau prenume



Dacă sunteți familiarizați cu Limbaj HTML, atunci totul ar trebui să vă fie clar, cel puțin până la eticheta formularului de deschidere. În interiorul acestei etichete se află cel mai important element al tuturor codurilor - atributul de acțiune. Ca acțiune pentru formularul nostru, am specificat numele fișierului nostru, apoi am aplicat șirul de interogare „ merge”.

Verificarea conformității cu criteriile

Când un utilizator introduce un prenume sau un nume de familie și apoi face clic pe butonul de trimitere, formularul transmite datele către sine și adaugă șirul de interogare „ merge”. În acest moment, verificăm prezența unui șir de interogare go. Dacă rezultatul este pozitiv, afișăm rezultatele căutării.

Înainte de a afișa rezultatele solicitate, trebuie să verificăm de două ori: (1) dacă formularul a fost trimis, (2) dacă șirul de interogare conține valoarea go, (3) dacă interogare de căutare introdus în partea de jos sau majuscule? Dacă niciunul dintre controale nu dă rezultat pozitiv (Adevărat), atunci nu suntem obligați să efectuăm nicio acțiune.

Mai întâi, să adăugăm un mic bloc de cod de căutare a site-ului PHP după eticheta de închidere.:



Mai întâi, deschidem un bloc de cod PHP cu eticheta „”.

Orice cod PHP din această pereche de etichete va fi executat de server. Apoi verificăm dacă formularul a fost trimis:

Introduceți termenul de căutare

"; } ?>

Vom folosi funcția isset încorporată, care returnează un bool și vom pune în ea matricea $ _POST. O expresie booleană în programare ne permite să obținem fie adevărat, fie fals.

Prin urmare, dacă funcția revine adevărată, atunci formularul a fost trimis și trebuie să continuăm să executăm codul în continuare. Dacă funcția revine falsă, atunci vom afișa un mesaj de eroare. Salvați tot codul tastat în fișierul search_submit.php.

Introduceți termenul de căutare

"; } } } ?>

Mai punem un condițional expresie booleanăîn interiorul celei principale, dar numai de data aceasta folosim matricea $ _GET împreună cu valoarea „ merge”. Salvați modificările în fișierul search_go.php.

Acum trebuie să ne asigurăm că vizitatorii pot introduce prima literă în șirul de interogare numai în partea de sus sau numai la minuscule... De asemenea, trebuie să oferim o modalitate de a ține cont de criteriile de căutare introduse de vizitator. Cel mai bine este să validați datele introduse de vizitator folosind o expresie regulată:

Am pus o altă expresie booleană condiționată în interiorul celor două. De data aceasta folosim o expresie regulată pentru a valida intrarea. Folosim funcția încorporată preg_match cu doi parametri: expresia regulată și câmpul formular care urmează să fie validat.

În cazul nostru, acesta va fi câmpul „Nume” ( Nume). Pentru a prelua parametrii de căutare furnizați de vizitator, creăm o variabilă $ name și îi legăm o valoare POST cu numele câmpului din formularul care va fi utilizat în interogarea SQL. Acum am implementat: (1) trimiterea datelor formularului, (2) șirul de interogare include o valoare go și (3) vizitatorul a introdus fie o primă literă cu majuscule, fie cu litere mici. Și toate aceste verificări se întâmplă chiar înainte ca modificările aduse bazei de date. Salvați toate modificările.

Conectați, selectați, interogați și returnați rezultatele din tabelul bazei de date

Pentru a obține datele din tabel, trebuie mai întâi să vă conectați la server în scriptul de căutare a site-ului. Pentru aceasta folosim următorul cod:

", "") sau die (" Nu mă pot conecta la baza de date deoarece: ". mysql_error ()); else (echo"

Vă rugăm să introduceți termenul de căutare

"; } } }?>

Creăm o variabilă $ db și o legăm de funcția MySQL încorporată mysql_connect, care ia trei parametri: serverul cu baza de date ( gazdă locală, dacă lucrați local), autentificare și parolă.

După aceea, vom rula funcția PHP încorporată, care oprește executarea codului suplimentar dacă nu există o conexiune la baza de date. Și afișăm informații despre eroare executând funcția MySQL încorporată mysql_error, care va returna motivul erorii. Salvați fișierul search_connectdb.php.

Vă rugăm să introduceți termenul de căutare

"; } } } ?>

Creați o variabilă numită mydb și legați-o de încorporat Funcțiile MySQL mysql_select_db, și apoi indicăm numele bazei de date pe care am creat-o mai devreme. Apoi, interogăm tabelul bazei de date folosind o interogare SQL cu variabila nume, care conține parametrii de căutare introduși de vizitator:

Vă rugăm să introduceți termenul de căutare

"; } } } ?>

Când interogăm un tabel de baze de date, creăm o variabilă $ sql și o legăm de rândul care conține interogarea SQL. Folosim o instrucțiune SELECT pentru a extrage valorile din coloanele id și numele și prenumele din tabelul de contacte. Apoi folosim clauza WHERE împreună cu valorile prenumelui și prenumelui pentru a restrânge căutarea.

Împreună cu operatorul LIKE, folosim semnul procent (%) - un caracter special care returnează 0 sau mai multe caractere, precum și variabila de nume din șirul de căutare. Ca urmare, LIKE ( combinat cu un personaj special) găsește orice nume care se potrivește în tabelul bazei de date. Întregul proces poate fi descris după cum urmează: „ Selectăm numele și prenumele din tabelul de contacte care se potrivesc cu cele introduse de vizitator". Salvați fișierul search_query.php.

Vă rugăm să introduceți termenul de căutare

"; } } } ?>

Creăm un rezultat $ variabil și îi atribuim valoarea funcției mysql_query (), injectându-l în $ interogare. Acum cererea noastră este stocată în variabila rezultat. Pentru a obține rezultatul în PHP, creăm o buclă și apoi scoatem datele într-o listă neordonată:

n "; ecou"

  • " . "
  • n "; ecou"";)) else (ecou"

    Vă rugăm să introduceți termenul de căutare

    "; } } } ?>

    Mai întâi, creăm o buclă while, în interiorul său, creăm o variabilă numită rând și o inițializăm cu valoarea returnată a funcției mysql_fetch_array, care ia rezultatul variabilei, care conține interogarea noastră SQL. Interior while loop atribuim fiecare valoare coloanei unei variabile cu același nume. Apoi vom afișa valorile din lista neordonată.

    Este important să fiți atenți la două puncte aici: (1) în interiorul buclei while, nu este necesar să atribuiți valorilor variabilelor matricei de rânduri, deoarece valorile pot fi luate direct din matricea de rânduri; (2) eticheta de ancorare pe care o folosim în numele fișierului împreună cu codul id și cheia principală. Motivul pentru aceasta este că multe elemente de căutare nu afișează inițial nimic.

    Deoarece afișăm doar numele și prenumele, atașând ID-ul la sfârșitul etichetei noastre de ancorare, putem folosi ID-ul pentru o cerere suplimentară care ne va permite să afișăm Informații suplimentare despre personal. Salvați fișierul și testați formularul de căutare a site-ului PHP ( search_display.php).

    Eliminați filele

    Rezultatele sunt afișate ca o listă neordonată, dar linia de jos este că nu avem nevoie de file. Pentru a scăpa de ea, adăugați următoarea regulă CSS chiar la începutul fișierului din cap:

    Căutare după scrisoare

    Este nevoie doar de câteva linii suplimentare de cod pentru a implementa o căutare după literă. Să adăugăm această funcționalitate convenabilă pentru vizitatori. În acest fel, vor putea să-i scrie pe reprezentanții personalului pe nume sau prenume.

    Adăugați următoarea linie de cod după eticheta formularului de închidere:

    A | B | K

    Legăm eticheta la șirul de interogare folosind o ancoră și setați-l la o anumită literă. Pentru a implementa funcționalitatea de căutare după literă, trebuie să adăugăm următorul cod imediat după acoladul de închidere din scriptul original, așa cum se arată mai jos:

    ) // Sfârșitul scriptului formularului de căutare if (isset ($ _ GET ["by"])) ($ letter = $ _ GET ["by"]; // Conectați-vă la baza de date $ db = mysql_connect ("servername" , "username", "password") sau die ("Nu mă pot conecta la baza de date deoarece:". mysql_error ()); // - Selectați baza de date $ mydb = mysql_select_db ("yourDatabase"); // - Interogați baza de date table $ sql = "SELECT ID, Prenume, Prenume DIN Contacte WHERE Prenume LIKE"% ". $ letter."% "SAU LastNAME LIKE"% ". $ letter."% ""; // - Executați interogarea funcției MySQL Query $ result = mysql_query ($ sql); // - Numărarea rezultatelor $ numrows = mysql_num_rows ($ result); echo "

    ". $ numrows." rezultate găsite pentru ". $ letter."

    "; // - Porniți bucla și sortați rezultatele în timp ce ($ rând = mysql_fetch_array ($ rezultat)) ($ FirstName = $ rând [" FirstName "]; $ LastName = $ rând [" LastName "]; $ ID = $ rândul ["ID"]; // - Imprimați rezultatul în ecoul matricei "
      n "; ecou"
    • "." ". $ Prenume." ". $ Prenume."
    • n "; ecou"
    "; } }

    Aici am schimbat patru fragmente din scriptul de căutare a site-ului:

    • Folosim funcția isset () și populăm matricea $ _GET, apoi verificăm valoarea;
    • Creați o literă $ variabilă și inițializați valoarea cu matricea $ _GET;
    • Adăugați variabila literă la interogarea SQL;
    • Specificăm litera variabilă în interiorul expresiei, în care obținem numărul numărat de linii.

    Salvați fișierul search_byletter.php și verificați rezultatul.

    Căutați un anumit angajat

    Pentru a afișa informații despre restul personalului, care sunt transmise printr-un id unic în cadrul link-ului nostru, trebuie să adăugăm următorul cod imediat după acoladul de închidere în scriptul literelor, așa cum se arată mai jos:

    ) // Sfârșitul scriptului if (isset ($ _ GET ["id"])) ($ contactid = $ _ GET ["id"]; // Conectați-vă la baza de date $ db = mysql_connect ("servername", " username "," password ") sau die (" Nu mă pot conecta la baza de date deoarece: ". mysql_error ()); // - selectați baza de date pentru a utiliza $ mydb = mysql_select_db (" yourDatabase "); // - Interogați baza de date date tabel $ sql = "SELECT * FROM Contacts WHERE ID =". $ contactid; // - Rulați o interogare la funcția mysql_query () $ result = mysql_query ($ sql); // - Porniți o buclă și sortați rezultatele în timp ce ($ rând = mysql_fetch_array ($ rezultat)) ($ Prenume = $ rând ["Prenume"]; $ Nume = $ rând ["NumeleNume"]; $ Număr de telefon = $ rând ["Număr de telefon"]; $ E-mail = $ rând [ „E-mail”]; // - Imprimați rezultatul în ecoul matricei ”

    "; } }

    Aici am schimbat patru bucăți de cod:

    • Folosim funcția isset () și odată cu aceasta verificăm valoarea ID-ului în matricea $ _GET;
    • Creați o variabilă $ contactid și inițializați-o cu matricea $ _GET;
    • În tabel, selectați tot ceea ce este marcat cu un asterisc *. Un asterisc este o abreviere în SQL care înseamnă „ dă-mi toate coloanele și rândurile din tabel "... Pentru a determina ce informații să afișăm, menționăm variabila contactid la sfârșitul instrucțiunii SQL;
    • Afișăm informații suplimentare despre fiecare reprezentant al personalului.

    Salvați fișierul search_byid.php și verificați rezultatul.

    Vă rugăm să rețineți că funcționalitatea noastră funcționează conform așteptărilor. Când introduceți un nume sau un nume în casetă sau când selectați o literă ca hyperlink, sunt afișate numai numele reprezentanților personalului. Dacă treceți cu mouse-ul peste link, puteți vedea un ID unic în bara de stare. Dacă faceți clic pe o anumită persoană, bara de adrese se va modifica și vor fi afișate informații suplimentare despre acest angajat.

    Injecție SQL

    Motivul pentru care am adăugat o expresie regulată în caseta noastră de căutare este astfel încât nimeni să nu poată altera interogarea noastră SQL. Această problemă era obișnuită, iar hackerii reușeau să-și execute propriile interogări SQL în timp ce vă manipulau aplicația. De exemplu, dacă am permis posibilitatea utilizării unui apostrof în câmpul nostru, atunci hackerul ar putea șterge pur și simplu baza de date folosind interogarea:

    "MESAJ DE DROP

    După cum sa menționat, regex-ul asigură faptul că vizitatorul poate introduce numai litere mici sau majuscule ca primul caracter.

    În concluzie

    În articolul de astăzi, am analizat cum să efectuăm o căutare pe site, precum și:

    • Creați baze de date și tabele conexe;
    • Folosiți instrumente pentru a gestiona baze de date, a crea coloane și a introduce date;
    • Elaborați formulare de căutare bazate pe PHP, care pot verifica datele de intrare, prezența variabilelor într-o interogare, precum și conectarea la o bază de date și afișarea rezultatelor dintr-un tabel;
    • Cum să vă protejați aplicația și baza de date de injecția SQL.

    Folosind cunoștințele acumulate din acest articol, puteți modifica cu ușurință codul altcuiva, precum și, dacă este necesar, extinde funcționalitatea formularului de căutare.

    Această publicație este o traducere a articolului " Cum se creează o funcție de căutare cu PHP și MySQL„Pregătit de echipa prietenoasă a proiectului