minicrispie: Benutzerabfrage in PHP+MySQL

Hallo,

ich hab da mal nen Problem in MySQL und PHP5 ...

Aussgangssituation:
In einer Tabelle namens "user" gibt es einen user namens "Admin".
(grober) Aufbau der Tabelle:

+--------------+
|  user        |
+--------------+
| ID           |
| benutzername |
+--------------+

Also ergibt sich für den ersten Datensatz:

+-------+
| user  |
+-------+
| 0     |
| Admin |
+-------+

Nun muss man annehmen, das die Datenbank später mehr User fasst. Somit wollte ich eine Benutzersuch-Funktion einbauen.

Problem:
Mit dem aktuellen Script will er mir nicht den Datensatz mit dem User "Admin" ausgeben, wenn ich für 'usersearch_name' "Adm" eingebe.
Als Ausgabe folgt immer "Keine Ergebnisse gefunden.".
Deswegen hab ich noch eine Testausgabe eingebaut( als Kommentar vermerkt ), welche mir die aktuelle Tabelle ausgeben soll. Diese Ausgabe lautet immer:

<table class="table_mitte"><tr class="table_head"><td>Name</td><td>Level</td></tr></table>

Script:

  
		//Alle Felder der Kathegorie müssen ausgefüllt werden  
		if( !empty($_POST['usersearch_name']) )  
		{  
			if( strlen( $_POST['usersearch_name'] ) > 0 )  
			{  
				//Existiert dieser User?  
				$sql    = "SELECT user.ID, user.benutzername, user.level FROM user WHERE user.benutzername = '%" . $_POST['usersearch_name'] . "%' LIMIT 10;";  
				$result = send_sql( $sql );  
				$names  = mysql_fetch_object( $result );  
				$anzahl = mysql_num_rows( $result );  
				  
				//if( $anzahl > 0 )  
				//{  
					$ausgabe = "<table class=\"table_mitte\"><tr class=\"table_head\"><td>Name</td><td>Level</td></tr>";  
					for( $i=0; $i<$anzahl; $i++ )  
					{  
						$ausgabe .= "<tr class=\"table_row\">";  
						$ausgabe .= "<td><a href=\"#\">" . $names->benutzername . "</a></td>";  
						$ausgabe .= "<td>" . $names->level . "</td>";  
						$ausgabe .= "</tr>";  
						$names = mysql_fetch_object( $result );  
					}  
					$ausgabe .= "</table>";  
				//}  
				//else  
				//{  
				//	$message = "Keine Ergebnisse gefunden.";  
				//}  
				  
				echo $ausgabe; //Testausgabe  
			}  
			else  
			{  
				$message = "Der Name muss mehr als 4 Zeichen beinhalten";  
			}  
		}  
		else  
		{  
			$message = "Keinen Namen angegeben.";  
		}  

Da ich momentan der einzige Nutzer der Datenbank bin, hab ich auf die überprüfung der Eingabe(escapen) verzichtet, da ich erst mal die grundlegende Funktion herstellen will.

MfG. Christoph Ludwig

--
Wo die Sprache aufhört, fängt die Musik an...
Selfcode:  sh:) fo:) ch:° rl:( br:^ n4:} ie:{ mo:} va:) js:| de:] zu:) fl:( ss:| ls:~
Go to this
  1. Moin!

    Problem:
    Mit dem aktuellen Script will er mir nicht den Datensatz mit dem User "Admin" ausgeben, wenn ich für 'usersearch_name' "Adm" eingebe.
    Als Ausgabe folgt immer "Keine Ergebnisse gefunden.".

    Ich vermute mal, es liegt an der eher als ungewöhnlich zu bezeichnenden Art, wie du das DB-Ergebnis auszugeben versuchst. Sowas macht man mit einer WHILE-Schleife, nicht mit FOR und vorheriger Abfrage der Ergebnisanzahl.

    Aber da du die Ergebnisanzahl ja abfragst: Was kommt da raus? Und was geht als Query-String an die Datenbank? Hast du den String auch mal manuell z.B. mit PhpMyAdmin getestet?

    - Sven Rautenberg

    1. Hallo,

      Ich vermute mal, es liegt an der eher als ungewöhnlich zu bezeichnenden Art, wie du das DB-Ergebnis auszugeben versuchst. Sowas macht man mit einer WHILE-Schleife, nicht mit FOR und vorheriger Abfrage der Ergebnisanzahl.

      nö, weil ich - wie vermutet - nicht am Schleifentyp liegt, sondern

      Aber da du die Ergebnisanzahl ja abfragst: Was kommt da raus? Und was geht als Query-String an die Datenbank? Hast du den String auch mal manuell z.B. mit PhpMyAdmin getestet?

      An der Anzahl, die mir zurückgegeben wird: 0
      Nur der SQL-String erscheint mir richtig:

      SELECT user.ID, user.benutzername, user.level FROM user WHERE user.benutzername = '%Adm%' LIMIT 10;

      Wenn ich das in PhpMyAdmin ausfürhe bekomme ich: "MySQL lieferte ein leeres Resultat zurück (d. h. null Zeilen). (die Abfrage dauerte 0.0005 sek.)"

      Ich weis mir keine Lösung :/

      MfG. Christoph Ludwig

      --
      Wo die Sprache aufhört, fängt die Musik an...
      Selfcode:  sh:) fo:) ch:° rl:( br:^ n4:} ie:{ mo:} va:) js:| de:] zu:) fl:( ss:| ls:~
      Go to this
      1. Hello,

        SELECT user.ID, user.benutzername, user.level FROM user WHERE user.benutzername = '%Adm%' LIMIT 10;

        Was fragst Du denn? Du sucht nach einem Benutzer, dessen Name gelich '%Adm%' ist. Hast Du denn einen solchen überhaupt in der Datenbank? Wolltest Du vielleicht nach einem Benutzer suchen, in dessen Name 'Adm' vorkommt? Dann solltest Du das auch so formulieren.

        Ähnlichkeitsabfrage mit LIKE
        Gleichheitsabfrage mit   =
        Enthält-Abfrage mit der passenden Stringfunkltion, von der MySQL eine Menge hat.
        http://dev.mysql.com/doc/refman/5.1/en/string-functions.html

        Außerdem würde ich einem gültigen Datensatz nicht die ID 0 verpassen, wenn es dafür nicht einen wichtigen Grund gibt. 0 eignet sich prima als neutrales Element und damit zur Kennzeichnung eines ungültigen Datensatzes, der dann natürlich auch nicht in die Tabelle aufgenommen wird.

        Die ID könntest Du auch als Autoincrement-Spalte anlegen. Die hätte dann besser keine 0 für gültige IDs.

        Liebe Grüße aus dem schönen Oberharz

        Tom vom Berg

        --
        Nur selber lernen macht schlau
        http://bergpost.annerschbarrich.de
        1. Hi Tom!

          Die ID könntest Du auch als Autoincrement-Spalte anlegen. Die hätte dann besser keine 0 für gültige IDs.

          Begründung?

          Der ID eines Datensatzes kommt keine semantische Bedeutung zu. Sie dient ausschließlich - oh Wunder ;-) - der Identifikation.
          OK, das widerlegt deine Forderung nicht. Ich behaupte aber, es ist egal, ob man mit 0, mit 1 oder mit 42 beginnt.

          Willst du darauf hinaus, dass 0 in PHP zu false ausgewertet wird?

          MfG H☼psel

          --
          "It's amazing I won. I was running against peace, prosperity, and incumbency."
          George W. Bush speaking to Swedish Prime Minister unaware a live television camera was still rolling, June 14, 2001
          Selfcode: ie:% fl:( br:> va:) ls:& fo:) rl:? n4:& ss:| de:] js:| ch:? sh:( mo:) zu:)
          1. Hello,

            Die ID könntest Du auch als Autoincrement-Spalte anlegen. Die hätte dann besser keine 0 für gültige IDs.
            Begründung?

            Der ID eines Datensatzes kommt keine semantische Bedeutung zu. Sie dient ausschließlich - oh Wunder ;-) - der Identifikation.
            OK, das widerlegt deine Forderung nicht. Ich behaupte aber, es ist egal, ob man mit 0, mit 1 oder mit 42 beginnt.

            Nein. Die 0 ist klar erkennbar als "ungültige ID" benutzbar. Selbstverständlich kann man, wenn man eine Datenbank nicht in der Praxis, sondern im Laborbetrieb betreiben will, auch jede andere ID als eindutig ungültige erklären. Im Laborbetrieb kann man vielleicht sogar daauf verzichten, da man dort ja für einfache Dinge locker irre aufwändige Sachen treiben kann. In der Praxis hat es sich allerdings  seit gut 90 Jahren automatsicher Datanverarbeitung bewährt, die 0 dafür zu benutzen.

            Viele Anfrageoberationen ergeben bei Ungültigkeit automatisch die 0. Es ist einfach, diesen Wert zu erkennen. Außerdem ist es bei Datenbanken üblich, dass der Index 0 außerhalb des gültigen Bereiches liegt. Warim sollte man also bei einer ID eine Ausnahme von dieser bequemen Regel machen?

            Vielleicht gitb es sogar in der Datanbanktheorie eine Begründung dafür, dass man die 0 als ungültigen Index, ungültige ID benutzen sollte, die kenne ich aber nicht und will auch, glaube ich, gar nicht danach forschen. :-)

            Liebe Grüße aus dem schönen Oberharz

            Tom vom Berg

            --
            Nur selber lernen macht schlau
            http://bergpost.annerschbarrich.de
            1. Hello,

              Viele Anfrageoberationen

              Also, jetzt muss ich doch mal nachhaken, wieso es so häufig passiert, dass beim Tippen statt eines p ein b, statt eines k ein g und so weiter reinrutscht.

              Bewußt betrachtet weiß ich doch, wie man die Worte schreibt, nur die Finger spielen da trotzdem auffällig oft einen Streich. Gibt es für diese Phänomen eine wissentschaftliche Erklärung?

              Liebe Grüße aus dem schönen Oberharz

              Tom vom Berg

              --
              Nur selber lernen macht schlau
              http://bergpost.annerschbarrich.de
            2. Hi,

              Die ID könntest Du auch als Autoincrement-Spalte anlegen. Die hätte dann besser keine 0 für gültige IDs.
              Begründung?

              Der ID eines Datensatzes kommt keine semantische Bedeutung zu. Sie dient ausschließlich - oh Wunder ;-) - der Identifikation.
              OK, das widerlegt deine Forderung nicht. Ich behaupte aber, es ist egal, ob man mit 0, mit 1 oder mit 42 beginnt.

              Nein. Die 0 ist klar erkennbar als "ungültige ID" benutzbar.

              Ausserdem kann man 0 auch beim INSERT benutzen, wenn man will, dass für eine auto_increment-Spalte der nächste freie Wert eingesetzt wird (auch wenn das Manual empfiehlt, dafür eher NULL zu verwenden).

              Und da das definiertes Verhalten darstellt, kann das später durchaus mal problematisch werden, wenn man den Wert 0 in einem INSERT-Statement hat, und auch diesen eingetragen haben will, und nicht den nächsthöheren freien - bspw. dann, wenn man einen Dump einspielt, in dem die auto_increment-IDs in den INSERTs enthalten sind, und diese aber nicht in sortierter Reihenfolge vorliegen.

              MfG ChrisB

              --
              Light travels faster than sound - that's why most people appear bright until you hear them speak.
  2. Hi minicrispie!

    $sql = "SELECT user.ID, user.benutzername, user.level FROM user WHERE user.benutzername = '%" . $_POST['usersearch_name'] . "%' LIMIT 10;";

    Wildcard-Vergleiche werden mit dem LIKE-Schlüsselwort gemacht.

    Beachte außerdem, dass dein Skript anfällig für SQL-Injection ist.

    MfG H☼psel

    --
    "It's amazing I won. I was running against peace, prosperity, and incumbency."
    George W. Bush speaking to Swedish Prime Minister unaware a live television camera was still rolling, June 14, 2001
    Selfcode: ie:% fl:( br:> va:) ls:& fo:) rl:? n4:& ss:| de:] js:| ch:? sh:( mo:) zu:)
    1. Hi minicrispie!

      Du solltest außerdem mit Aliasnamen (Stichwort: Umbenennung von Spalten) arbeiten. Dann ist deine SQL-Abfrage wartungsfreundlicher bzgl. der Änderung von Tabellennamen.

      MfG H☼psel

      --
      "It's amazing I won. I was running against peace, prosperity, and incumbency."
      George W. Bush speaking to Swedish Prime Minister unaware a live television camera was still rolling, June 14, 2001
      Selfcode: ie:% fl:( br:> va:) ls:& fo:) rl:? n4:& ss:| de:] js:| ch:? sh:( mo:) zu:)
    2. Hallo,

      Wildcard-Vergleiche werden mit dem LIKE-Schlüsselwort gemacht.

      och nö ... nur wegen so nem ... WAHHHH ... gut, jetz funktionierts

      Beachte außerdem, dass dein Skript anfällig für SQL-Injection ist.

      Da hatte ich schon was geschrieben: Da ich momentan der einzige Nutzer der Datenbank bin, hab ich auf die überprüfung der Eingabe(escapen) verzichtet, da ich erst mal die grundlegende Funktion herstellen will.

      hmm OK Danke!

      MfG. Christoph Ludwig

      --
      Wo die Sprache aufhört, fängt die Musik an...
      Selfcode:  sh:) fo:) ch:° rl:( br:^ n4:} ie:{ mo:} va:) js:| de:] zu:) fl:( ss:| ls:~
      Go to this
      1. Hallo Christoph,

        » Beachte außerdem, dass dein Skript anfällig für SQL-Injection ist.

        Da hatte ich schon was geschrieben: Da ich momentan der einzige Nutzer der Datenbank bin, hab ich auf die überprüfung der Eingabe(escapen) verzichtet,

        das ist eine ganz schlechte Idee mit einer fehlerhaften Begründung.

        da ich erst mal die grundlegende Funktion herstellen will.

        Das einfachste von der Welt ist es, Daten *nie* für den Kontext aufzubereiten, in dem sie verwendet werden. Dann fällt man halt ziemlich oft auf die Schnauze.

        Das zweiteinfachste von der Welt ist es, Daten *immer* für den Kontext aufzubereiten, in dem sie verwendet werden. Dann fällt man *nie* auf die Schnauze.

        Das komplizierteste von der Welt ist es, zu überlegen, wann man auf die kontextgerechte Behandlung verzichten kann. Dann fällt man nach Murphy genau dann auf die Schnauze, wenn man es am wenigsten gebrauchen kann.

        Wenn Du also Deine ersten Gehversuche mit MySQL und PHP ausgerechnet mit den veralteten und wenig leistungsfähigen mysql_*-Funktionen machen willst, dann benutze mysql_real_escape_string(), um Deine Werte kontextgerecht aufzubereiten. Ach ja, gegebenenfalls musst Du noch die Magic Quotes vorher entschärfen.

        Diese guten Ratschläge kannst Du im Forumsarchiv hundertfach nachlesen, eine kleine Erläuterung der kontextgerechten Behandlung von Werten für Einsteiger hab' ich erst vor ein paar Tagen geschrieben (zwar nicht für MySQL, aber das spielt keine Rolle).

        Ach so noch eine Bemerkung: Selbstverständlich solltest Du Deine Ausgabe für den HTML-Kontext aufbereiten, so wie Du das im verlinkten Beitrag nachlesen kannst.

        Wir wären hier ganz schlecht beraten, wenn wir Dich nicht auf diese grundlegenden und extrem schwerwiegenden Fehler aufmerksam machten. Beachte sie und Du wirst es später Dir selbst danken.

        Freundliche Grüße

        Vinzenz