[PHP] Suchfunktion

Martu

@
ID: 303421
L
25 Mai 2006
186
32
Hi,

ich bräuchte mal Hilfe wegen einer Suchfunktion. Also ich habe in einer MySQL Tabelle die Spalten ID, NAME, TAGS, INFOS, BILD. Es geht hier um eine Pflanzendatenbank für unsern Garten. Bei der Spalte Bild handelt es sich nur um den Pfad zur Bilddatei. In der Spalte Tags stehen Alternativnamen der Pflanze, abgetrennt mit einem Leerzeichen. Jetzt habe ich hier schonmal eine Abfrage erstellt mit Formular aber es passiert nichts. Ich will TAGS und NAME durchsuchen.

PHP:
<?php
mysql_connect("localhost","zensiert","zensiert") or die ("Keine Verbindung");
mysql_select_db("zensiert") or die ("Datenbank existiert nicht");
$i = $_GET["suche"];
$abfrage = "SELECT * FROM garten1 WHERE TAGS == '%$i%'";
$query = mysql_query($abfrage);
while($row = mysql_fetch_object($query))
{
echo $row->name;
}
?>

Irgendwie geht es nicht :(
 
Wenn du nach Tags und Name durchsuchen lassen willst, musst du gucken, ob es in Tags einen Treffer gibt oder in Name einen Treffer gibt.

Aber bitte - ein Tip: Du solltest deine Datenbank wenigstens in die erste Normalform bringen :pray:
 
Okay, danke für die schnelle Hilfe. Was ist die erste Normalform?

Und die jetzige Abfrage funktioniert nicht, da erscheint folgende Fehlermeldung:

Code:
Warning: mysql_fetch_object(): supplied argument is not a valid MySQL result resource in /usr/export/www/vhosts/funnetwork/hosting/uououo/suchfunktion.php on line 21
 
Code:
Warning: mysql_fetch_object(): supplied argument is not a valid MySQL result resource in /usr/export/www/vhosts/funnetwork/hosting/uououo/suchfunktion.php on line 21
[PHP/MySQL] supplied argument is not a valid MySQL result resource
Wird wohl am doppelten Gleichheitszeichen liegen, aber guck bitte selber nach und probier ned wild rum.
Was ist die erste Normalform?
Oha. Guckst du in die Wiki:
https://de.wikipedia.org/wiki/Normalisierung_(Datenbank)#Erste_Normalform_.281NF.29

Wenn du die erste Normalform erreicht hast, kannst du auch die Tags ordentlich durchsuchen.
 
Okay, die Abfrage geht jetzt nur leider ohne irgendein Ergebnis, was wohl an der Verletzung der ersten Normalform liegt. Ich versteh was die erste Normalform ist, kann sie aber gerade nicht auf meine Datenbank anwenden, mir fehlt das Wissen, kannst du mir vielleicht helfen oder noch ein Beispiel geben?
 
Das Problem ist das Spielchen mit den Leerzeichen.

Im Moment hast du:
Code:
Tabelle: garten1
Spalten: ID, NAME, TAGS, INFOS, BILD
(die 1 in garten1 deutet schon wieder auf eine Verletzung hin 8O)

TAGS ist aber nicht atomar, sondern eine Liste von Tags, also wird diese Spalte in eine neue Tabelle ausgelagert:
Code:
Tabelle: garten1
Spalten: [U]ID[/U], NAME, [COLOR=Red][s]TAGS[/s][/COLOR], INFOS, BILD

[COLOR=SeaGreen]Tabelle: garten1tags
Spalten: [U]GARTEN1ID[garten1], [/U][/COLOR][U][COLOR=SeaGreen]TAG[/COLOR][/U]
Ich wiederhol das an dieser Stelle nochmal: Diese komische "1", die ich hier mitschlepp, ist vermutlich auch falsch.
Hast du mehrere Gärten in weiteren, identischen garten-Tabellen?
 
Also diese 1 habe ich da nur hingeschrieben, falls ich vorhab für Bekannte weitere Gartendatenbanken zu erstellen. Ich kann die 1 auch gerne rausstreichen ^^

Also ich habe jetzt verstanden was du meinst. Nur wie verknüpfe ich die TAG-Tabelle mit der Gartentabelle, hat glaub ich etwas mit einem Indexschlüssel zutun. Der Tabellenschlüssel ist bei "garten1" auf ID gesetzt, soll ich ihn bei der TAG-Tabelle auch auf ID setzen?

Tut mir Leid wenn ich mich etwas blöd anstelle, aber ich hab doch recht beschränkte Kenntnisse :(
 
Also mal als Tip:

mach 2 spalten

pflanzenname | alternativname
tulpe | alternativname_1
tulpe | alternativname_2

so hast du nur einen Namen und nicht mit Leerzeichen getrennte Bezeichnungen, aber das hat dir ja theHacker schon geschrieben.

Deine Abfrage geht wohl nicht, weil du da die %-Zeichen drin hast. mach die mal weg. oder willst du mit LIKE suchen?
 
Tut mir Leid wenn ich mich etwas blöd anstelle, aber ich hab doch recht beschränkte Kenntnisse :(
Mit beschränkten Kenntnissen kommt auch nur Beschränktes raus. Ein paar Grundkenntnisse wären nicht verkehrt ;)

Also diese 1 habe ich da nur hingeschrieben, falls ich vorhab für Bekannte weitere Gartendatenbanken zu erstellen. Ich kann die 1 auch gerne rausstreichen ^^
Die sollte raus.
Wenn du wirklich mehrere Gärten anlegen willst, muss das auch ordentlich gemacht werden. Im Moment machen wir nur einen Garten.
Der Tabellenschlüssel ist bei "garten1" auf ID gesetzt, soll ich ihn bei der TAG-Tabelle auch auf ID setzen?
Der Primary-Key ist in der Notation unterstrichen. Bei der neuen Tabelle muss er über beide Felder gehen.
Also ich habe jetzt verstanden was du meinst. Nur wie verknüpfe ich die TAG-Tabelle mit der Gartentabelle, hat glaub ich etwas mit einem Indexschlüssel zutun.
Verknüpft wird normalerweise mit JOIN.

In unserem Szenario brauchst du aber ne zweite Abfrage zum Suchen.
Zuerst suchst du alle Datensätze, die die gewünschten Tags beinhalten (du kannst jetzt auch nach mehreren Tags suchen, wenn du willst).
PHP:
$gartenids = array();
$res = mysql_query("SELECT DISTINCT GARTENID FROM gartentags 
                    WHERE TAG LIKE '%foo%' OR TAG LIKE '%bar%'");
while($row = mysql_fetch_assoc($res))
  $gartenids[] = $row['GARTENID'];
mysql_free_result($res);
Du hast damit im Array alle IDs der Gärten, die du haben willst.

Nun selektiere alle Gärten:
PHP:
$gartenids = implode(', ', $gartenids);
$res = mysql_query("SELECT NAME, INFOS, BILD FROM garten 
                    WHERE ID IN ($gartenids);");
/* ... */
Ich bin jetzt mal davon ausgegangen, dass die Tags nur zum Suchen benutzt werden.

edit:
Noch ein Tip: Schreibe Spaltenname klein, dann kann man sie besser von den SQL-Schlüsselwörtern unterscheiden. Ich hab mich jetzt mal an deine Benennung gehalten. Du siehst: Is nicht grad recht schön, zu lesen.
 
PHP:
$i = $_GET["suche"];
$abfrage = "SELECT id FROM garten1tags WHERE tag LIKE '$i'";
$query = mysql_query($abfrage);
while($row = mysql_fetch_object($query))
{
$verw = $row->id;
}
$abfrage2 = "SELECT name, infos FROM garten1 WHERE id = '$verw'";
$query2 = mysql_query($abfrage2);
while($row = mysql_fetch_object($query2))
{
echo "<a href=\"index.html?get=$verw\">$row->name</a>";
}

So hab ich das jetzt gemacht, ich hoffe es ist einigermaßen in Ordnung *gg
Jetzt will ich noch eine Abfrage für die "name"-Spalte machen, doch wie sage ich der if-Anweisung dass bei der tag-Abfrage nichts rausgekommen ist?

edit: Okay, ich habs schon =)
 
Ein paar Sachen noch:

  • $i benutzt man normaler Weise als Schleifenzähler. Variablen ordentlich benennen, also z.B. $suchstring etc.
  • IDs sind eigentlich immer Integer, also lass die komischen Hochkommata in der Datenabfrage bei den IDs weg.
  • Rück den Code ordentlich ein, wenn ihn mal ein anderer lesen muss. Außerdem erleichert es dir auch das Leben.
Jetzt will ich noch eine Abfrage für die "name"-Spalte machen, doch wie sage ich der if-Anweisung dass bei der tag-Abfrage nichts rausgekommen ist?
Mit mysql_num_rows() kannst du ein MySQL-Resultset prüfen, ob Ergebnisse drin sind. Wenn 0, dann wurde nichts gefunden.
 
PHP:
$i = $_GET["suche"];
$abfrage = "SELECT id FROM garten1tags WHERE tag LIKE '$i'";
$query = mysql_query($abfrage);
Offengesagt, macht mich hier etwas unglücklich, dass eine Usereingabe direkt an die Datenbank übergeben wird, ohne das Du weißt was drinnen steht.

Das solltest Du Dir schon vom grundsatz her, erst gar nicht angewöhnen. Schau mal hier: https://de.wikipedia.org/wiki/SQL-Injection da werden die Auswirkungen und mögliche Gegenmaßnahmen genannt.
 
Was ich hier auch grad noch sehe:
PHP:
$abfrage = "SELECT id FROM garten1tags WHERE tag LIKE '$i'";
$query = mysql_query($abfrage);
while($row = mysql_fetch_object($query))
{
$verw = $row->id;
}
Was soll der Quark? Du selektierst alle Treffer aus der Datenbank und läuft sie dann alle durch, nur um das letzte Ergebnis zu bekommen. Das macht keinen Sinn.
 
Ja das ist echt quark, aber ich habe deine Lösung da oben fast garnicht verstanden, weil ich nicht weiß was jeder Befehl da bringt. Da dacht ich mir ein Suchergebnis reicht, aber das wär ja wohl ne ziemlich dumme Suchfunktion. mysql_fetch_assoc habe ich nie gehört, usw. Ich muss es immer ganz nachvollziehen, um es zu raffen :( Sorry, und wenn ich in Google die Befehle absuche versteh ich es auch nicht zur Gänze, PHP programmiert hab ich das letzte Mal vor 2 Jahren und das auch nicht besser wie jetzt :hö:

@paulrene:
Ja das weiß ich, hab mich schon viel über SQL-Injection informiert aber da ich gerade sowieso Probleme mit dem Script habe wollte ich mir nicht auch noch die SQL-Injection um den Kopf hauen. Hab mir gedacht das füge ich zum Schluss ein.
 
@Eistee, sowas "vergisst" man später grundsätzlich.
Also ich kann als Tipp nur mitgeben; entweder mit einem Datanbanklayer arbeiten und das Framework das regeln lassen (würde jetzt aber den Rahmen sprengen) oder das sofort bei jeder Abfrage integrieren.

Zu den Befehlen oben, Du kannst da nicht einfach die Hälfte weglassen. ;)
Wenn eien variable mit $var[] angeben wird, handelt es sich um ein Array was einfach gefüllt wird. Wenn Du $var angibst, wird ein Wert in eine Variable geschrieben.
Mit dem Implode werden die IDs das SQL Suchergebnis "zusammengebastelt" um sie in die neue Suchabfrage aufzunehmen.


Offen gesagt, hätte ich die Tabellen aber wohl über ein Join verknüpft. Ich wüsste nicht, wieso das Script Datenbankaufgaben erledigen sollte.
Oder hab ich da was übersehen/nicht verstanden @TheHacker?
 
Offen gesagt, hätte ich die Tabellen aber wohl über ein Join verknüpft. Ich wüsste nicht, wieso das Script Datenbankaufgaben erledigen sollte.
Oder hab ich da was übersehen/nicht verstanden @TheHacker?
Mit einem Join in einer 1:N-Beziehung wuerde er aber die 1-Spalten N-mal kriegen, was evtl. irritieren koennte.
 
Schon, aber dann gruppiert man das eben noch und gut ist? :roll:
Zwar nicht schick aber ich finds dann doch hübscher als die getrennten querys.