Joe: Datenbankabfrage in Klasse

Hallo Forum

Ich habe mir in PHP eigens für Datenbankabfragen eine Klasse geschrieben. Nun möchte ich in einer Funktion query(), die den Abfragestring übergeben bekommt, ebendiesen Abfragestring auswerten.
Je nachdem ob es sich nun um ein SELECT oder INSERT handelt, möchte ich im Falle eines SELECT die ausgewählten Zeilen (in einem indizierten Array) und im Falle eines INSERT true (oder false bei Fehler) zurückgeliefert bekommen.
Wenn es nämlich ein INSERT ist, möchte ich nicht mittels mysql_fetch_row() die Zeilen in mein indiziertes Array auslesen, da dies einen Fehler erzeugt.
Wie kann ich jetzt mit den PHP-eigenen mysql-Funktionen herausfinden, ob es sich bei der Abfrage um ein SELECT, INSERT, ... handelt?
Oder ist meine einzige Möglichkeit über String-Funktionen den Abfragestring zu überprüfen?

MFG
Joe

  1. Hallo Joe,

    Wie kann ich jetzt mit den PHP-eigenen mysql-Funktionen herausfinden, ob es sich bei der Abfrage um ein SELECT, INSERT, ... handelt?
    Oder ist meine einzige Möglichkeit über String-Funktionen den Abfragestring zu überprüfen?

    Entweder machst du das, oder du gibt einfach einen weiteren Parameter an deine Funktion (z. B. einen Parameter $querytype, der eine bestimmte Konstante übergibt, die du natürlich vorher definierst). Das können dann durchaus Zeichenketten sein.
    Das fände ich jedenfalls die sinnvollste Variante.

    Das könnte dann beispielsweise so aussehen:

      
    // benötigte Konstanten initialisieren  
    define('MYSQL_QUERYTYPE_SELECT', 0);  
    define('MYSQL_QUERYTYPE_INSERT', 1);  
      
    /**  
     * Klasse zum speziellen Zugriff auf eine MySQL-Datenbank  
     */  
    class Mysql {  
      
      /**  
       * Führt einen MySQL-Query aus und gibt eventuell vorhandene Resultate zurück  
       *  
       * @param   $query      Der auszuführende MySQL-Query  
       * @param   $querytype  Der Typ des MySQL-Querys - wird der Parameter nicht angegeben, wird ein SELECT-Query angenommen  
       * @return  Ergebnis des ausgeführten Querys bei Erfolg  
       */  
      function query($query, $querytype = MYSQL_QUERYTYPE_SELECT) {  
      
        switch ($querytype) {  
        case MYSQL_QUERYTYPE_SELECT:  
          /* Code einfügen */  
          break;  
        case MYSQL_QUERYTYPE_INSERT:  
          /* Code einfügen */  
          break;  
        }  
      
      }  
      
    }
    

    Aufgerufen werden könnte das Ganze dann beispielsweise so (ich gehe jetzt davon aus, dass die MySQL-Verbindung bereits steht und eine existierende Datenbank ausgewählt wurde - am sinnvollsten macht man dies übrigens im Konstruktor der Mysql-Klasse):

      
    $mysql = new Mysql();  
    $result = $mysql->query('SELECT id,name,message FROM guestbook');
    

    Dies ist so möglich, weil als Standardwert ein SELECT angenommen wird.
    Will man einen INSERT anwenden, so könnte der Aufruf so lauten:

      
    $result = $mysql->query('INSERT ... INTO guestbook', MYSQL_QUERYTYPE_INSERT);
    

    Alles klar? :)

    Grüße

    Marc Reichelt || http://www.marcreichelt.de/

    --
    Linux is like a wigwam - no windows, no gates and an Apache inside!
    Selfcode: ie:{ fl:| br:> va:} ls:< fo:} rl:( n4:( ss:) de:> js:| ch:? sh:| mo:) zu:)
    http://emmanuel.dammerer.at/selfcode.html
    1. Alles klar? :)

      Ja alles klar, nur schade, denn genau diese Lösung wollte ich vermeiden.
      Da es aber anscheinend nicht anderes geht, danke ich dir vielmals.
      MFG
      Joe

      1. Hallo Joe,

        Ja alles klar, nur schade, denn genau diese Lösung wollte ich vermeiden.
        Da es aber anscheinend nicht anderes geht, danke ich dir vielmals.

        Natürlich geht es anders. Du hast doch selbst geschrieben - man kann die ersten n Buchstaben auslesen und prüfen, ob darin "SELECT" oder "INSERT" steht (Groß- / Kleinschreibung natürlich nicht beachten).

        Und es geht noch anders: Auf php.net stehen zur Funktion mysql_query()  die Rückgabewerte beschrieben. Kannst du damit etwas anfangen?

        Ich würde beispielsweise einfach den Rückgabewert prüfen, und in der selbst geschriebenen Funktion query() weiter übergeben - also z. B. so:

          
        if ($result === true || $result === false) {  
          return $result;  
        }
        

        Das '===' steht übrigens für absolute Identität, also genau dann wenn auch die Typen der beiden zu vergleichenden Ausdrücke übereinstimmen.

        Grüße

        Marc Reichelt || http://www.marcreichelt.de/

        --
        Linux is like a wigwam - no windows, no gates and an Apache inside!
        Selfcode: ie:{ fl:| br:> va:} ls:< fo:} rl:( n4:( ss:) de:> js:| ch:? sh:| mo:) zu:)
        http://emmanuel.dammerer.at/selfcode.html
  2. Hallo Freunde des gehobenen Forumsgenusses,

    Je nachdem ob es sich nun um ein SELECT oder INSERT handelt, [...]

    In PHP würde ich das so lösen (ungetestet):

      
    /**  
    * Überprüft, ob eine SQL-Query ein SELECT ist.  
    *  
    * @param string SQL-Query, die überprüft werden soll.  
    * @return bool true, wenn es sich um ein SELECT handelt, sonst false.  
    */  
    function is_select($sql) {  
     if (substr(strtolower(ltrim($sql)), 0, 6) == 'select')  
      return true;  
     return false;  
    }  
    
    

    Gruß
    Alexander Brock

    1. echo $begrüßung;

      Je nachdem ob es sich nun um ein SELECT oder INSERT handelt, [...]

      In PHP würde ich das so lösen (ungetestet):
      if (substr(strtolower(ltrim($sql)), 0, 6) == 'select')

      Die Lösung hat nur einen Haken: Sie ist unflexibel. Sie mag vielleicht mehr als 90% aller Fälle abdecken, doch irgendwann wird jemand kommen und ein anderes Statement als SELECT ausführen wollen, das eine Ergebnismenge zurückliefert (SHOW TABLES etc.), oder SELECT ... INTO OUTFILE, was zwar ein SELECT ist aber keine Ergebnismenge liefert.
      Also plädiere auch ich für die Auswertung des Rückgabewertes von mysql_query():

      false: Fehler aufgetreten
      true: Statement ausgeführt, keine Ergebnismenge
      Ressource: Statement ausgeführt, Ergebnismenge vorhanden.

      echo "$verabschiedung $name";

  3. der gedankliche ansatz einer db-klasse trennt einen aufgabenbereich ab. besser wäre es aber, in objekten zu denken und diese abzutrennen.
    wenn die db-klasse nur weiterleitet und mit kompletten strings versorgt wird, ergibt sich das problem der erkennung dieses strings.
    besser wäre es daher, der db-klasse keine kompletten sql-strings zu geben, sondern mit dieser in logischen blöcken zu arbeiten und die db-klasse selbst den benötigten sql-string aufbauen zu lassen. so ergibt sich auch nicht das problem, den string zu parsen um festzustellen was mit dem string eigentlich bezweckt werden soll.

    ich habe auf http://fanelf.de/Dokumentation/Persistenz.htm eine demo wie so etwas aussehen kann. es lohnt sich, dieses zu verstehen.

    1. echo $begrüßung;

      der gedankliche ansatz einer db-klasse trennt einen aufgabenbereich ab. besser wäre es aber, in objekten zu denken und diese abzutrennen.

      Ja. Das ist aber erst der nächste Schritt in der Entwicklung von der Eizelle zum Programmierweltmeister :-)

      Es gibt bereits Lösungen für beide Schritte im PHP Extension and Application Repository - auch PEAR genannt: DB, DB_DataObject, DB_Table. (MDB sei auch noch erwähnt, aber das kenne ich nicht weiter.)

      echo "$verabschiedung $name";

      1. man will ja nicht gleich mit der tür ins haus fallen. jeder muß seine erfahrungen machen. deshalb fängt wohl jeder erst einmal ganz einfach an, bevor er sich hin zu konzepten entwickelt.

        der gedankengang eine db-schicht abzutrennen ist oft die erste stufe. dies beachtet aber noch nicht eine multi-tier architekture. erst hier entstehen wirklich saubere und pflegbare konzepte, da die schnittstellen einfach, offen, abstrakt und nicht auf eine bestimmte anforderung der anderen seite zugeschnitten sind.

        im rahmen dieses gedankenganges spielen dann nur objekte mit der anwendungslogik. einige von diesen müssen natürlich persistiert werden.  dies erledigt dann eine separate schicht. ob diese dann ein rdbms oder eine andere alternative dafür verwendet, spielt in der anwendungsschicht keine rolle, da diese im grunde genommen nicht einmal kenntnis davon hat.

        moderne softwarearchitekturen sind nun mal objektorientiert. nur so lassen sich vernünftige programme erstellen. dies ist bei erstellern von php-gewurschtel nicht immer der fall.

        haben diese jedoch erst einmal java-enterprise kennen gelernt, werden diese auf das saubere konzept auch nicht in php nicht verzichten wollen. nur so lassen sich stressfrei geniale programmstrukturen erstellen.

        1. Hallo Freunde des gehobenen Forumsgenusses,

          moderne softwarearchitekturen sind nun mal objektorientiert. nur so lassen sich vernünftige programme erstellen. dies ist bei erstellern von php-gewurschtel nicht immer der fall.

          Ich habe für meinen bayesschen Filter in PHP folgendes Konzept:

          1. Eine Klasse, die die Verbindung zum mysqld herstellt, Queries entgegennimmt und abschickt und das Ergebnis liefert.

          2. Eine Klasse, die SQL-Queries zusammenbaut und an die erste Klasse weitergibt.

          3. Eine Hauptklasse, die mit den Ergebnissen der zweiten Klasse rechnet und Texte in die Filterdatenbank einpflegt.

          Was haltet ihr von diesem Konzept?

          Gruß
          Alexander Brock