Autosuggest mit PHP & Vue.js
Mittlerweile ist es Standard: Wenn wir im Browser oder bei einer Suchmaschine beginnen unseren Suchbegriff einzutippen, erhalten wir Vorschläge mit passenden Suchbegriffen.
In diesem Post zeige ich euch, wie sich eine einfache Variante mit Vue.js und PHP umsetzen lässt.
Was ist Vue.JS?
Vue.js ist ein modernes JavaScript-Framework, mit dem sich dynamische Webanwendungen bequem und einfach umsetzen lässt. Ich persönlich nutze Vue.js gerne, da es sich sehr einfach auch in bestehende Web-Anwendung integrieren lässt. So können alte, schwerfällige reine HTML & PHP-Anwendungen Stück für Stück dynamisch gestaltet werden.
Mit Vue.js lassen sich diverse Applikationen einfach und bequem umsetzen: To-Do-Listen, Warenkörbe, Tabellen inklusive Sortierung und Filterung, Foren, Gästebücher und vieles mehr. Ebenfalls lässt sich mit Vue.js bequem diverse Suchfunktionen umsetzen, die z.B. erforderlich sind wenn man eine große Vergleichsseite betreibt wie beispielsweise casino-ohnelizenz.com
Als generelle Einführung für Vue.js, kann ich folgenden Guide empfehlen: Vue.js - Get started
Datenbank-Struktur
Zuerst brauchen wir eine Liste mit möglichen Suchbegriffen. Diese können wir recht einfach bekommen, indem wir protokollieren, wonach gesucht wird. Dafür erstellen wir eine neue Datenbank-Tabelle:
1 2 3 4 5 6 7 8 9 10 |
CREATE TABLE `search_queries` ( `query` varchar(255) NOT NULL, `num_searched` int(11) NOT NULL DEFAULT 1, `last_searched` timestamp NOT NULL DEFAULT current_timestamp() ON UPDATE current_timestamp() ) ENGINE=InnoDB DEFAULT CHARSET=latin1; ALTER TABLE `search_queries` ADD UNIQUE KEY `query` (`query`); COMMIT; |
In dieser Tabelle speichern wir den Suchbegriff, die Anzahl der durchgeführten Suchen für diesen Begriff und wann dieser zuletzt gesucht wurde.
Such-Backend
Als nächstes erstellen wir ein Such-Backend (search.php): Ein PHP-Script, dass einen Such-Query entgegen nimmt. Diesen Suchbegriff speichern wir in der zuvor erstellten Tabelle ab:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
<?php header('Content-Type: application/json'); $pdo = new PDO('mysql:host=localhost;dbname=test', 'root', ''); $query = $_GET['query'] ?? ''; $statement = $pdo->prepare("INSERT INTO search_queries (query) VALUES (?) ON DUPLICATE KEY UPDATE num_searched=num_searched+1"); $statement->execute([$query]); $response = [ "query" => $query, "date" => date("d.m.Y H:i:s"), "grad_heute" => rand(-15, 35), "grad_morgen" => rand(-15, 35), ]; echo json_encode($response); |
Da wir in der Tabelle query als unique definiert haben, können wir ON DUPLICATE KEY nutzen um den Zähler für die Anzahl an Suchen um 1 zu erhöhen, wenn erneut danach gesucht wird.
Als Rückgabewert geben wir den Suchbegriff zurück, das aktuelle Datum, und zwei Zufallszahlen für die Gradzahl Heute und morgen. Bei einer realen Anwendung müsste man hier natürlich noch die entsprechende Suche implementieren.
Autosuggest-Backend
Als nächstes erstellen wir das Backend für die Suchvorschläge (suggest.php):
1 2 3 4 5 6 7 8 9 10 |
<?php header('Content-Type: application/json'); $pdo = new PDO('mysql:host=localhost;dbname=test', 'root', ''); $query = $_GET['query'] ?? ''; $statement = $pdo->prepare("SELECT query FROM search_queries WHERE query LIKE ? ORDER BY num_searched DESC LIMIT 5"); $statement->execute([$query.'%']); $data = $statement->fetchAll(PDO::FETCH_COLUMN, 0); echo json_encode($data); |
Hier fragen wir alle Datenbank-Einträge ab, die mit der Eingabe starten. Diese werden absteigend nach der Suchhäufigkeit sortiert. Ebenfalls limitieren wir die Anzahl auf 5.
Wenn wir also z.B. suggest.php?query=Wetter B eintippen, werden Suchbegriffe wie Wetter Berlin und Wetter Bochum vorgeschlagen.
Vue.js Frontend
Nun kommen wir zu dem Teil, wo wir Vue.Js nutzen. Hier benötigen wir drei Komponenten:
- Ein Suchfeld inklusive Button für die Suche
- Ein Liste mit unseren Suchvorschlägen
- Ein Feld zur Darstellung der Suchergebnisse
Vollständig sieht der HTML-Code wie folgt aus:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 |
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Suche</title> <!-- Vue.js --> <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script> <!-- Axios - Für AJAX Aufrufe --> <script src="https://cdn.jsdelivr.net/npm/axios/dist/axios.min.js"></script> <style> .search_row { display: flex; padding: 10px; } .search_row > div { margin: 5px; } .search_dropdown { border: 1px solid #111111; } </style> </head> <body> <div id="app"> <div class="search_row"> <div>Suche:</div> <div> <input v-model="query" v-on:keyup="suggest()"> <br> <div class="search_dropdown" v-if="suggest_items.length > 0"> <div v-for="item in suggest_items"><a href="#" v-on:click="query=item; search()">{{item}}</a></div> </div> </div> <div> <button v-on:click="search()">Suchen</button> </div> </div> <br><br> <div v-if="search_response"> <b>Ergebnisse:</b><br> <b>Query:</b> {{ search_response.query }} <br> <b>Datum:</b> {{ search_response.date}} <br><br> <b>Wetter:</b> Heute {{search_response.grad_heute}}°C, morgen {{search_response.grad_morgen}}°C </div> </div> <script> var app = new Vue({ el: '#app', data: { query: '', search_response: null, suggest_items: [] }, methods: { search: function() { this.suggest_items = []; axios.get('search.php?query='+encodeURIComponent(this.query)) .then(response => (this.search_response = response.data)) }, suggest: function() { axios.get('suggest.php?query='+encodeURIComponent(this.query)) .then(response => (this.suggest_items = response.data)) } } }) </script> </body> </html> |
Zuerst die Suchleiste: Hier haben wir das Input-Feld, einen Button der die tatsächliche Suche ausführt und ein Anzeigefeld, für die Suchvorschläge (sofern suggest.php Ergebnisse liefert):
1 2 3 4 5 6 7 8 9 10 11 12 13 |
<div class="search_row"> <div>Suche:</div> <div> <input v-model="query" v-on:keyup="suggest()"> <br> <div class="search_dropdown" v-if="suggest_items.length > 0"> <div v-for="item in suggest_items"><a href="#" v-on:click="query=item; search()">{{item}}</a></div> </div> </div> <div> <button v-on:click="search()">Suchen</button> </div> </div> |
Sofern Ergebnisse von search.php vorliegen, zeigen wir diese in dem folgendem div an:
1 2 3 4 5 6 7 8 |
<div v-if="search_response"> <b>Ergebnisse:</b><br> <b>Query:</b> {{ search_response.query }} <br> <b>Datum:</b> {{ search_response.date}} <br><br> <b>Wetter:</b> Heute {{search_response.grad_heute}}°C, morgen {{search_response.grad_morgen}}°C </div> |
Nun der eigentlich spannende Teile, der entsprechende Vue.js Code der alles zusammenführt:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
<script> var app = new Vue({ el: '#app', data: { query: '', search_response: null, suggest_items: [] }, methods: { search: function() { this.suggest_items = []; axios.get('search.php?query='+encodeURIComponent(this.query)) .then(response => (this.search_response = response.data)) }, suggest: function() { axios.get('suggest.php?query='+encodeURIComponent(this.query)) .then(response => (this.suggest_items = response.data)) } } }) </script> |
Wir definieren zwei Methoden: search wird ausgeführt, wenn wir auf den Such-Button klicken. Hier wird search.php aufgerufen und die Rückgabe wird unter this.search_response gespeichert.
Sobald wir etwas in das Suchfeld eintippen, wird die Methode suggest() aufgerufen: Diese fragt das suggest.php Backend nach passenden Suchbegriffen ab. Diese werden in this.suggest_items abgespeichert.
Autor: Nils Reimers