Autocomplete | PHP MySQL Jquery

diggakool

Mitglied
Moin,

ich habe eine Suche die Einträge aus der Datenbank holt und abgleicht.

Ich habe einen Eintrag der heisst z.B. "Alle Apfelbäume haben grüne Blätter".

Jetzt gebe ich in die Suche z.B.: "Apfelbäume Blätter alle grüne" ein.
Hier soll er mir nun auch den Eintrag zeigen aber macht er leider nicht, da die Wörter in einer anderen Reihenfolge sind.

Wie schaffe ich es, dass er auch ohne richtige Reihenfolge diesen Eintrag mit auflistet?

Hier ist mein bisheriger Code:

Suche
HTML:
<input id="satz" name="satz" type="text" placeholder="..." autofocus />

Script
Code:
$(document).ready(function(){    
    $("#satz").autocomplete({
  minLength: 3,
  async: false,
source: function(request, response) {
    $.ajax({
      url: "suche.php",
      data: request,
      dataType: "json",
      type: "POST",
      success: function(data){
          response(data);
      }
    });
  }
	});

PHP
Code:
$dbhost = 'localhost';
$dbuser = 'root';
$dbpass = 'root';
$dbname = 'datenbank';
 
try {
  $conn = new PDO("mysql:host=$dbhost;dbname=$dbname", $dbuser, $dbpass);
}
catch(PDOException $e) {
    echo $e->getMessage();
}
 
$return_arr = array();
 
if ($conn)
{
    $ac_term = "%".utf8_decode($_POST['term'])."%";    
    
    $query = "SELECT * FROM saetze where Satz like '%{$ac_term}%' ORDER BY Satz";
    $result = $conn->prepare($query);
    $result->bindValue(":term",$ac_term);
    $result->execute();

    while ($row = $result->fetch(PDO::FETCH_ASSOC)) {           
        $row_array['value'] = $row['Satz']; 
        array_push($return_arr,$row_array);
    }     
}

$conn = null; 

echo json_encode($return_arr); 

?>
 
Ich würde den Satz einfach auseinander nehmen und Wort für Wort vergleichen:
PHP:
/* ... */

$hotwords = explode( " ", $_POST[ "term" ] );
$hotwords = array_filter( $hotwords, function ( $item ) {
  return !empty( $hotwords );
});
array_walk( $hotwords, function ( $item ) {
  $item = "`Satz` LIKE '%" . $item . "%'";
});

$where = implode( " AND ", $hotwords );
$query = "SELECT * FROM `saetze` WHERE {$where} ORDER BY `Satz`";

/* ... */

EDIT: Korrektur siehe Beitrag von saftmeister weiter unten.
 
Zuletzt bearbeitet:
Hier mal was ähnliches:

PHP:
<?php
// display them...
error_reporting(-1);
ini_set('display_errors', 1);

// prepare db connection
$pdo = new PDO('mysql:host=localhost;dbname=test', 'test', null, array(PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION));
$pdo->query("set names 'utf8'");

// cleanup first
$pdo->query("drop table if exists baz");

// start the action
$pdo->beginTransaction();

// create a temporary table
$stmt = $pdo->prepare("create table baz (id int not null auto_increment, headline varchar(50), content text, primary key (id))");
$stmt->execute();

// insert some valuable content
$stmt = $pdo->prepare("insert into baz (headline, content) values (?, ?)");
$stmt->bindValue(1, 'Alle Apfelbäume haben grüne Blätter');
$stmt->bindValue(2, 'Irgendwann im April...');
$stmt->execute();
$stmt->bindValue(1, 'Meine Katze frisst mir die Haare vom Kopf');
$stmt->bindValue(2, 'Aber nur morgens bis abends');
$stmt->execute();

// prepare the search
$stmt = $pdo->prepare("select * from baz where headline like ?");

$searchString = 'Apfelbäume Blätter alle grüne';
$keywords = explode(' ', $searchString);

// now start the search
$results = array();
foreach($keywords as $keyword)
{
  // each loop checks for the current keyword
  $stmt->bindValue(1, "%$keyword%");
  $stmt->execute();
  // loop over results and store them in a save container
  while($row = $stmt->fetch(PDO::FETCH_OBJ))
  {
    // only add results which are not fetched yet
    if(!array_key_exists($row->id, $results))
    {
      $results[$row->id] = clone $row;
    }
  }
}

// check the results
var_dump($results);

// revert anything...
$pdo->rollBack();
 
moin einfach nur crack!

danke für deine antwort.

leider funktionert das nicht.
jetzt zeigt er gar nichts mehr an außer "[]" in der suche.php.
 
Aber das heißt doch, saftmeister, dass Du für jedes enthaltene Wort eine eigene Abfrage startest – das ist aus meiner Sicht viel aufwendiger, als wenn man alles in einer Abfrage handhabt.
 
danke saftmeister.

cracks antwort macht für mich auch mehr sinn aber irgendwie haut das noch nicht ganz hin.
die überlegung ist aber gut.
 
Aber das heißt doch, saftmeister, dass Du für jedes enthaltene Wort eine eigene Abfrage startest – das ist aus meiner Sicht viel aufwendiger, als wenn man alles in einer Abfrage handhabt.

Naja, ein ganz klares jain. Es handelt sich um ein Prepared Statement. Man kann das ganze sicher noch optimieren, aber im Grunde macht man in der Hochsprache nichts anderes, als der SQL-Server ohnehin tut.
 
Zuletzt bearbeitet:
Was mir aber grad aufgefallen ist: mein Ansatz hat einen gravierenden Nachteil: Es werden möglicherweise sehr viele Datensätze von der DB abgeholt, die bereits gefetched wurden. Das erhöht dann natürlich das Datenaufkommen und das PHP-Script läuft ggf. länger. Daher macht er wirklich weniger Sinn, als alles in WHERE-Conditions zu packen.

Anmerkung zu alxy's Beitrag: Der Fulltext-Index funktioniert nur bei MyISAM, Innodb bietet das nicht an. Daher abwägen, was wichtiger ist, schnelle Textsuche oder referentielle Integrität.
 
Zurück