php mysql_num_rows() errorhandling

  • Wenn ich einen neuen User in der Datenbank anlegen will, dann frage ich zuvor nach wieviele User mit diesem Namen bereits existieren.



    Das Problem ist nur das dieser Ausdruck

    PHP
    if (mysql_num_rows($result) > 0) {

    auch dann true ergibt wenn ein Fehler passiert (Ich hab zB zu Testzwecken in der SELECT Query einen tippfehler eingebaut (SELECT * FROM fm5_user WHERE useraname='$username') und der falsche if zweig ausgeführt wird.

    Wie gehts richtig?

    dankesehr

    david

    I like Toast!

  • Vielleicht

    PHP
    if(mysql_error()) {
        /* fehler in der abfrage */
    }
    else {
        /* ... */
    }

    Btw. SQL-Injection kennst du eh, oder?

  • nö, nicht wirklich.

    Hatte aber das Wort schon im Hinterkopf und hätte danach gegoogelt?

    Würde mich aber auch nicht wehren wenn du mir ein paar Sätze darüber bzw. was man dagegen tun kann schreibst.

    :)

    david

    I like Toast!

  • Siehe mysql_query(), dort mußt du den Fehler abfangen, nicht bei mysql_num_rows(). Also z.B.

    PHP
    if (($res = mysql_query($query) === FALSE) {
      // blah
    }
    
    
    // oder auch...
    $res = mysql_query($query) or die("blah");

    Hab das jetzt nicht getestet (gibt PHP den Wert einer Zuweisung eh wieder als Wert zurück?), aber grundsätzlich geht das so.

    Oder, wie ich grad sehe, so wie Paulchen es gepostet hat. Meine Lösung ist aber eleganter. ;)

    Paulchen hat recht was das Thema SQL Injection betrifft - schau dir das mal lieber an. Du solltest statt

    PHP
    $query = "SELECT username FROM fm5_user WHERE username='$username'";

    auf jeden Fall

    PHP
    $query = "SELECT username FROM fm5_user WHERE username='" . mysql_real_escape_string($username) . "'";

    benutzen.

  • Ja, sonst kommt der böse Paul und gibt als Benutzernamen

    Code
    blabla'; DROP TABLE fm5_user WHERE 1=1 OR username='bla

    ein und dann kommt als Abfrage

    SQL
    SELECT username FROM fm5_user WHERE username='blabla'; DELETE FROM fm5_user WHERE 1=1 OR username='bla'

    heraus. :devil:

  • Du hättest halt grad noch Glück weil sich MySQL eh weigert, mehrere Befehle innerhalb einer Query zu akzeptieren. ;) Dem Paulchen würd aber sicher noch was noch teuflischeres einfallen.

  • Zitat von bosie

    nimm lieber gespeicherte prozeduren

    Was angesichts der Tatsache, dass es die erst ab MySQL 5 gibt, leider nicht immer möglich ist.

  • Zitat von Paulchen

    Was angesichts der Tatsache, dass es die erst ab MySQL 5 gibt, leider nicht immer möglich ist.

    hm, wo wird erwähnt, dass er nicht mysql 5 hat?

  • Zitat von bosie

    hm, wo wird erwähnt, dass er nicht mysql 5 hat?

    Meine Aussage hat sich nicht konkret auf den vorliegenden Fall bezogen.

  • hatte vor allem kein php5 aber habs nun lokal installiert (unet.univie rennt nur php 4)

    Andre Frage (SQL Injections wären gelöst)

    PHP
    // escape special characters to prevent SQL Injection
    	public function quote_smart($query) {
    		// Quote if not a number or a numeric string
    		if (!is_numeric($query)) {
    			$query = "'" . mysql_real_escape_string($query, $this->db) . "'";
    		}
    		return $query;
    	}

    Ich scheitere ein wenig an folgendem:
    Wenn ein User zum ersten mal auf die Seite kommt, dann wird ne Session gestartet.
    Ich würde gern ein Objekt DatabaseController verwenden welches den Zugriff auf die MySQL Datenbank kapselt.
    Dieses soll ein Singleton werden, also einmal erzeugt und dann immer nur die Instanz geholt, aber irgendwie funktioniert das nicht so wie ich will.

    und im Code mach ich ein include auf das file und dann zB

    PHP
    include_once("DatabaseController.php");
    $dbc = DatabaseController::instance();

    I like Toast!

  • Zitat von davewood
    PHP
    // escape special characters to prevent SQL Injection
    	public function quote_smart($query) {
    		// Quote if not a number or a numeric string
    		if (!is_numeric($query)) {
    			$query = "'" . mysql_real_escape_string($query, $this->db) . "'";
    		}
    		return $query;
    	}

    Es tut dir nicht weh, auch Zahlen zu escapen und unter Anführungszeichen an MySQL zu schicken. Ich würde das im Zweifelsfall einfach immer machen, dann kann man auch nicht darauf vergessen.

    Siehe dazu z.B. auch den Code aus einem Kommentar im PHP-Manual, scheint mir recht praktisch zu sein:

    [QUOTE=davewood]Dieses soll ein Singleton werden, also einmal erzeugt und dann immer nur die Instanz geholt, aber irgendwie funktioniert das nicht so wie ich will.

    Der Code scheint auf den allerersten Blick in Ordnung zu sein, was genau geht denn nicht?

  • hum.

    das objekt wird bei jedem seiteaufruf (also in meinem fall dann wenn ich einen ajax request schicke) neu instantiiert, die if abfrage in

    PHP
    public static function instance() {
       if (!is_object($dbc)) {
          $dbc = new DatabaseController();
       }
       return $dbc;
    }


    ergibt scheinbar immer true (also dass es sich um kein objekt handelt)

    hab grad keinen php5 server verfügbar um das nochmals zu testen.

    david

    I like Toast!

  • Zitat von beefy

    Es tut dir nicht weh, auch Zahlen zu escapen und unter Anführungszeichen an MySQL zu schicken.


    Ich benutze dafür gerne is_numeric(). Dann weiß ich nämlich auch gleich, ob die Eingabe der Erwartung entspricht, bevor die Query vielleicht schiefgeht; und wenn is_numeric() == true, dann ist auch escapen unnötig. Z. B. einfach

    Code
    if (!is_numeric($userid))
            exit false;

Jetzt mitmachen!

Sie haben noch kein Benutzerkonto auf unserer Seite? Registrieren Sie sich kostenlos und nehmen Sie an unserer Community teil!