Evidentiere cuvinte in cautare mysql cu match against

Discutii despre script-uri si coduri PHP-MySQL, precum si lucru cu XML in PHP.
cadou
Mesaje:328

Evidentiere cuvinte in cautare mysql cu match against

Salut.
Am incercat sa fac search in mysql cu match() against(), dar nu prea imi pare mie ok.
nu se boldeaza toate cuvintele gasite .... doar daca scriu doua cuvinte unul dupa altul boldeaza ...
si cateodata imi da eroare la linia 6, linia 6 fiind

Cod: Selectaţi tot

$programe = $dbh->query("SELECT COUNT(*) FROM `test` WHERE MATCH (denumire,descriere) AGAINST ('$search')")->fetch(PDO::FETCH_NUM);
Am creat un tabel de test asa :
universitateamaritimaconstanta.tk/1.jpg

iar codul este urmatorul :

Cod: Selectaţi tot

<?php include('conectare.php');
if($_POST) 
{
$search = $_POST['searchword'];

$programe = $dbh->query("SELECT COUNT(*) FROM `test` WHERE MATCH (denumire,descriere) AGAINST ('$search')")->fetch(PDO::FETCH_NUM);
$rezprograme = $programe[0];

// asociere rezultate //
$rowprograme = $dbh->query("SELECT * FROM `test` WHERE MATCH (denumire,descriere) AGAINST ('$search') ORDER BY RAND() LIMIT 5");

if($rezprograme == 0)
{ ?>
<div class="display_box" align="left" style="color:red;">
     <center>
         Fara rezultate. Este posibil sa nu existe momentan pe site ceea ce cauti! <br>
         <b>Sfat: Scrie corect ceea ce doresti sa cauti! </b>
     </center>
</div><?php }
else {
// daca se gaseste ceva in programe //
if($rezprograme > 0) {
    while ($searchs = $rowprograme->fetch(PDO::FETCH_ASSOC)){
$final = str_ireplace($_POST['searchword'], '<b><font color="red" size="3">'.ucwords($_POST['searchword']).'</font></b>', ''.ucwords($searchs['denumire']).'');
$finals = str_ireplace($_POST['searchword'], '<b><font color="red" size="3">'.ucwords($_POST['searchword']).'</font></b>', ''.ucwords($searchs['descriere']).''); ?>
<a href="/programe.php#program<?php echo $search['id']; ?>" style="text-decoration:none;" target="_blank">
    <div class="display_box" align="left;color:red;">
        <?php echo $final; ?>
    </div>
</a>

<a href="/programe.php#program<?php echo $search['id']; ?>" style="text-decoration:none;" target="_blank">
    <div class="display_box" align="left;color:red;">
        <?php echo $finals; ?>
    </div>
</a>

<?php }
}
// end rezultate programe //
}
}
?>

MarPlo Mesaje:4343
Nu stiu de ce si cand apare eroare la acea linie de cod; probabil la anumite caractere din fraza cautata.
Ca sa evidentiezi cuvintele cautate in rezultatele din Select, cred ca am merge daca aplici str_ireplace() la fiecare cuvant din fraza cautata ($_POST['searchword']), dupa separare cu explode().
Incearca asa:

Cod: Selectaţi tot

$arr_src = explode(' ', trim($_POST['searchword']));
$nr_src = count($arr_src);
while($searchs = $rowprograme->fetch(PDO::FETCH_ASSOC)){
  $final = $searchs['denumire'];
  $finals = $searchs['descriere'];
  for($i=0; $i<$nr_src; $i++){
    $final = str_ireplace($arr_src[$i], '<span style="color:red;font-weight:700;font-size:18px;">'.$arr_src[$i].'</span>', $final);
    $finals = str_ireplace($arr_src[$i], '<span style="color:red;font-weight:700;font-size:18px;">'.$arr_src[$i].'</span>', $finals);
  }
} 

cadou Mesaje:328
Te rog frumos sa il faci tu acest cod php de la cap la coada ...
te rog din suflet, am nevoie enorm de el.
Cautarea dupa mai multe cuvinte in mai multe tabele ... + evidentiere cuvinte cautate si gasite :(

Am incercat cateva variante dar nu am reusit nimic inca ... de cateva zile ma tot chinui si nu ajung nicaieri ....

MarPlo Mesaje:4343
Posteaza ce ai incercat. da un exemplu si spune ce nu iese cum vrei.
Te pot ajuta pe codul tau fiindca tu stii despre ce e vorba. Tu ai acele tabele, modul in care sunt definite si in ce coloane sa cauti.

- Daca din cauza unor probleme de hosting nu se poate adauga cond aici, poti sa iti faci cont pe: coursesweb.net/forum/ si scrii acolo in engleza.

cadou Mesaje:328
scuze pentru raspunsul intarziuat.
revin cu codul

Cod: Selectaţi tot

<?php include('conectare.php');
if($_POST)
{
$search = $_POST['searchword'];
$arr_src = explode(' ', trim($_POST['searchword']));
$nr_src = count($arr_src);

$intrebari = $dbh->query("SELECT COUNT(*) FROM `intrebari` WHERE MATCH (nume, intrebare) AGAINST ('$search')")->fetch(PDO::FETCH_NUM);
$rezintrebari = $intrebari[0];
// asociere rezultate //
$rowintrebari = $dbh->query("SELECT * FROM `intrebari` WHERE MATCH (nume, intrebare) AGAINST ('$search') ORDER BY RAND() LIMIT 5");

if($rezintrebari == 0)
{ ?>
<div class="display_box" align="left" style="color:red;">
  <center>
   Fara rezultate. Este posibil sa nu existe momentan pe site ceea ce cauti! <br>
   <b>Sfat: Scrie corect ceea ce doresti sa cauti! </b>
  </center>
</div><?php }
else {
// cautare intrebari //
if($rezintrebari > 0) {
$arr_src = explode(' ', trim($_POST['searchword']));
$nr_src = count($arr_src);
while($searchs = $rowintrebari->fetch(PDO::FETCH_ASSOC)){
  $final = $searchs['nume'];
  $finals = $searchs['intrebare'];
  for($i=0; $i<$nr_src; $i++){
        $final = str_ireplace($arr_src[$i], '<span style="color:red;font-weight:700;font-size:18px;">'.$arr_src[$i].'</span>', $final);
        $finals = str_ireplace($arr_src[$i], '<span style="color:green;font-weight:700;font-size:18px;">'.$arr_src[$i].'</span>', $finals);
?>
<a href="/intrebare/<?php echo "$search[adresa]";?>.php" style="text-decoration:none;" target="_blank">
<div class="display_box" align="left;color:red;">
  <?php echo $finals; ?>
</div>
</a> 
<?php  }
}
}
// end search intrebari //
}
}
?>


MarPlo Mesaje:4343
M-am uitat pe cod, dar nu inteleg care e problema. Ce nu iese cum vrei, partea de cautare, rezultatee din select sau partea de evidentiere cuvinte cautate?

cadou Mesaje:328
De exemplu primesc eroare la linia 8

Cod: Selectaţi tot

Fatal error: Call to a member function fetch() on a non-object in ............./test.php on line 8

$intrebari = $dbh->query("SELECT COUNT(*) FROM `intrebari` WHERE MATCH (nume, intrebare) AGAINST ('$search')")->fetch(PDO::FETCH_NUM);


MarPlo Mesaje:4343
Eroarea legata de fetch() inseamna ca mysql returneaza eroare sau false; e ceva gresit la acel Select.
In codul php, dupa definirea conectarii, in "conectare.php", adauga si aceasta setare ca sa poata captura erorile de la mysql

Cod: Selectaţi tot

$dbh->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
Incearca sa faci Select-ul cum e in acest exemplu, cu try ...catch() ca sa captureze si ce eroare returneaza mysql.

Cod: Selectaţi tot

//where the $dbh is defined, add this to set to capture the mysql errors
$dbh->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);

$err =[];  //store errors
$src_html ='';  //store html code to output

$arr_src = explode(' ', trim($_POST['searchword']));
$nr_src = count($arr_src);

$sql ="SELECT * FROM intrebari WHERE MATCH (nume, intrebare) AGAINST ('$search') ORDER BY RAND() LIMIT 5";

//execute rhe query and capture errors
try {
  $intrebari = $dbh->query($sql, PDO::FETCH_BOTH);
}
catch(PDOException $e){
  $err[] = $e->getMessage();
}

//if errors, add to output the errors, else use the results
if(count($err) >0) $src_html = implode('<br>', $err);
else {
  //parse the results
  while($row = $intrebari->fetch()){
    $re_intr = $row['intrebare'];

    //evidentiate the searched words
    for($i=0; $i<$nr_src; $i++){
      $re_intr = str_ireplace($arr_src[$i], '<span style="color:red;font-weight:700;font-size:18px;">'.$arr_src[$i].'</span>', $re_intr);
    }
    $src_html .= $re_intr .'<br>';
  }
}

echo $src_html;  //output final html 

cadou Mesaje:328
m-am uitat pe codul atasat... am incercat sa il inteleg, si am modificat putin ceva la codul meu trimis initial.
pentru tabela "programe" am urmatoarea cerere in baza de date pentru a afla daca am rezultate sau nu

Cod: Selectaţi tot

$dbh->query("SELECT COUNT(*) FROM programe WHERE MATCH (denumire, descriere) AGAINST ('$search')")->fetch(PDO::FETCH_NUM); 

desi caut ceva ce exista in baza de date primesc raspuns negativ, ca nu exista nimic, orice caut in baza de date primesc ca nu exista.

pentru tabela "intrebari" unde am urmatoarea cerere in baza de date sa vad daca am rezultate sau nu

Cod: Selectaţi tot

$dbh->query("SELECT COUNT(*) FROM intrebari WHERE MATCH (intrebare) AGAINST ('$search')")->fetch(PDO::FETCH_NUM); 
asta macar imi afiseaza rezultate daca exista, chiar daca nu este asa cum vreau eu.
Ma refer la faptul ca eu daca scriu sa caut " vaccin febra galbena" iar eu in baza de date am " vaccinul febrei galbene" el nu gaseste nimic, adica el cauta exact cum scriu eu , nu ceva asemanator ...
sper ca am fost inteles si mi-ai inteles ideea ....

MarPlo Mesaje:4343
Am inteles ideea. Cautarea cu MATCH() AGAINST() are anumite limitari.
1. Cuvintele care sunt in mai mult de 50% din tabel sunt considerate comune si nu le ia in considerare.
2. Nu stie de sinonime sau asemanare de cuvinte. Ce ii spui exact sa caute aceea cauta. Chiar si cu instructiunea LIKE dai de aceasta limitare, daca ii dai sa caute "galbena" nu va gasi "galbene". Un script care sa fie asa de "destept" e complicat de facut, necesita o baza de date cu sinoime pentru majoritatea cuvintelor, plus un algoritm de calcul pentru siungular si plural.
MATCH() AGAINST() are mai multe moduri de cautare: "IN NATURAL LANGUAGE MODE", "IN BOOLEAN MODE" si "WITH QUERY EXPANSION" care se adauga la AGAINST().
De exemplu poti incerca:

Cod: Selectaţi tot

$dbh->query("SELECT COUNT(*) FROM programe WHERE MATCH (denumire, descriere) AGAINST ('$search', WITH QUERY EXPANSION)")->fetch(PDO::FETCH_NUM);
- Poti sa studiezi documentatia la: https://dev.mysql.com/doc/refman/5.6/en ... earch.html

Sau poti sa incerci cu LIKE. Uite o functie facuta pentru asa ceva setSrcLike(), in plus sterge din fraza de cautare caracterele non alfa-numerice si cuvintele mai mici de 3 caractere.

Cod: Selectaţi tot

// return string between parentheses with valid words in LIKE statement to search
// Receives: $str =search-phrase from user; $col =column from mysql table where to apply LIKE
function setSrcLike($str, $col) {
  // replace '-' with space. Delete non alfa-numeric-space characters. Replace 2+ spaces with single space
  $str = str_replace('-', ' ', $str);
  $str = preg_replace('/[^a-z0-9_ ]+/i', '', $str);
  $str = preg_replace('/\s+/i', ' ', trim($str));
  $str = explode(' ', $str);  //make an array of words from $str

  // add words with $col and LIKE
  $re = [];
  foreach($str AS $word) {
    if(strlen($word) <=2) continue;  //ignore 1 and 2 letter words
    $re[] ="$col LIKE '%$word%'";
  }

  return '('. implode(' OR ', $re) .')';  //return with (OR between LIKEs) and parentheses
}

$search ='vaccin pt. febra galbena';
$like_den = setSrcLike($search, 'denumire');  //LIKE for column denumire
$like_des = setSrcLike($search, 'descriere');  //LIKE for column descriere
$sql ="SELECT * FROM programe WHERE ". $like_den ." OR ". $like_des ." LIMIT 8";
//Then apply query() to $sql

//Test to see resulted $sql
echo $sql;
// SELECT * FROM programe WHERE (denumire LIKE '%vaccin%' OR denumire LIKE '%febra%' OR denumire LIKE '%galbena%') OR (descriere LIKE '%vaccin%' OR descriere LIKE '%febra%' OR descriere LIKE '%galbena%') LIMIT 8