Ankündigung

Einklappen
Keine Ankündigung bisher.

OOP Klassen und Sortierung von Resultaten

Einklappen

Neue Werbung 2019

Einklappen
X
  • Filter
  • Zeit
  • Anzeigen
Alles löschen
neue Beiträge

  • OOP Klassen und Sortierung von Resultaten

    Ich hab da mal eine allgemeine Frage wie ihr das in eurem Projekten so löst was das filtern und sortieren von Datenbankabfragen betrifft.

    Ich habs bei mir so gelöst dass ich eine eigene Sortier Helper Klasse aufbaue. Zum Beispiel so:

    PHP-Code:
    class sorter {

        
    // Sort a Multidimensional array by a given value and direction
        
    public function sortMultiArray($array,$value,$direction "asc"){
            foreach(
    $array as $k=>$v) {
                
    $b[$k] = strtolower($v[$value]);
            }
            if(
    $direction == "asc"){
                
    asort($b);
            }else{
                
    arsort($b);
            }
            foreach(
    $b as $key=>$val) {
                
    $c[] = $array[$key];
            }
            return 
    $c;
        }

    Daneben hab ich eine Klasse mit der ich Beispielsweise Events aus der Datenbank hole:

    PHP-Code:
    class events {

        function  
    __construct() {
            
    // Set the database connection
            
    $this->con = new clientDB();
            
    $this->con->db->setAttribute(PDO::ATTR_ERRMODEPDO::ERRMODE_SILENT);

            
    // Get all Events into our object
            
    $sql $this->con->db->prepare("Select * from db_eventIndex");
            
    $sql->execute();
            
    $this->events $sql->fetchAll(PDO::FETCH_ASSOC);
        }

        
    // Get project dependet events
        
    function setFilterProject($pID){
            
    $i 0;
            foreach(
    $this->events as $event){
                if(
    $event["projectID"] <> $pID){
                    unset(
    $this->events[$i]);
                }
                
    $i++;
            }
        }

        
    // Get user dependet events
        
    function setFilterUser($uID){
            
    $i 0;
            foreach(
    $this->events as $event){
                
    // See on which event I'm connected
                
    $sql $this->con->db->prepare("Select * from db_eventMembers WHERE userID = ? and eventID = ?");
                
    $sql->bindValue(1,$uID,PDO::PARAM_STR);
                
    $sql->bindValue(2,$event["ID"],PDO::PARAM_STR);
                
    $sql->execute();
                
    $res $sql->fetch(PDO::FETCH_ASSOC);
                if(
    $res["eventID"] <> $event["ID"]){
                    unset(
    $this->events[$i]);
                }
                
    $i++;
            }
        }
           
        
    // Throw the events
        
    function dropEvents(){
            return 
    $this->events;
        } 
    Natürlich gibt es sehr viele solche Klassen die mir Listen mit Daten ausgeben. Diese kann ich dann schön bequem wie folgt sortieren und ausgeben lassen:

    PHP-Code:
    <?PHP
                $events 
    = new events();
                
    $events->setFilterUser($_SESSION["system"]["user"]["id"]);

                
    $mylist = new sorter();
                
    $mylist $mylist->sortMultiArray($events->dropEvents(), "eventStart");

                if(
    count($mylist) > 0){
                    foreach(
    $mylist as $event){
                        
    $eventDate = new date($event["eventStart"]);
                        echo 
    '<li>'.$eventDate->getDate().' - '.$event['eventName'].'</li>';
                    }
                }else{
                    echo 
    "<p>Zur Zeit keine anstehenden Termine.</p>";
                }
                
    ?>
    Meine Frage an euch Profis ist nun ob dies eine saubere Methode ist oder ob ihr da in der Praxis die Thematik anders löst.

    Beispielsweise auch die Frage, hole ich mir die Daten gefiltert aus der Datenbank und bastle das spezifische SQL Query in meiner Klasse zusammen und feure es erst bei der Ausgabe ab, oder lad ich die Datensätze in mein Objekt und filtere dieses dann?

    Für eure Feedbacks bedanke ich mich herzlich.

    Grüsse

    eXe

  • #2
    Also ich weiss nicht wie deine Datenbank aussieht, aber bei größeren Applikationen (gerade auch beim Einsatz von ORMs wo du noch zig andere Infos und Objekt-Beziehungen hast) kannst du so schnell an die Memory Grenze stößen.

    Kommentar


    • #3
      Ich halte es generell so, dass Sortierung und Filterung in der Datenbank verbleibt. Da muss ich mich nicht darum kümmern, wenn mal große Datenmengen in einer Tabelle stecken und ich mit LIMIT arbeiten muss. Deine Klasse wird in solch einem Fall vermutlich abschmieren und meckern, dass nicht genug Speicher allocated werden kann.

      Zusätzlich kann die Sortierung in PHP anders aussehen, als in SQL. Kollationen, Zeichensätze und die Art der Sortierung (numerisch, alphabetisch, ...) können sich stark unterscheiden.

      Deine Methode zum sortieren ist aber deswegen nicht schlecht. Es gibt hin und wieder für solche Methoden auch Anwendungsfälle. Ein Tipp noch am Rand: Mach aus "public function sortMultiArray" "public static function sortMultiArray". Dann kannst du dir das Objekt sparen.

      Kommentar


      • #4
        Ja, die ganze Filterung sollte soweit wie möglich, auf dem DB Server passieren.

        IMHO ist es Schwachsinn, ALLE Elemente aus der DB zu holen (1000e) und dann den kompletten Array nach einer ID zu durchsuchen und alles andere zu löschen.

        Kommentar


        • #5
          [OT]

          mein Blog
          Falls ich hier wie das Boardarschloch rüberkomme => Das ist vollste Absicht!
          lol, jetzt neu nach "Sido -mein Block" : "ragtek - mein Blog"

          (sorry, konnts mir nicht verkneifen)
          [/OT]

          Kommentar


          • #6
            Zitat von ragtek Beitrag anzeigen
            Ja, die ganze Filterung sollte soweit wie möglich, auf dem DB Server passieren.
            Gehört IMHO auch in die Datenbank und nicht in den PHP-Code.
            Sicherlich gibt es auch mal Ausnahmen, wo es in der DB nicht geht, aber das wird wohl eher seltener passieren.

            Kommentar


            • #7
              Zitat von Paul.Schramenko Beitrag anzeigen
              Gehört IMHO auch in die Datenbank und nicht in den PHP-Code.
              Sicherlich gibt es auch mal Ausnahmen, wo es in der DB nicht geht, aber das wird wohl eher seltener passieren.
              Das meine ich ja damit

              Kommentar


              • #8
                Zitat von da.eXecutoR Beitrag anzeigen
                PHP-Code:
                class events {

                    function  
                __construct() {
                        
                // Set the database connection
                        
                $this->con = new clientDB();
                        
                $this->con->db->setAttribute(PDO::ATTR_ERRMODEPDO::ERRMODE_SILENT);

                        
                // Get all Events into our object
                        
                $sql $this->con->db->prepare("Select * from db_eventIndex");
                        
                $sql->execute();
                        
                $this->events $sql->fetchAll(PDO::FETCH_ASSOC);
                    }

                    
                // ... 
                statt $this->events = $sql->fetchAll(PDO::FETCH_ASSOC); kannst du auch $this->events = $sql; verwenden, die PDOStatement Objekte funktionieren auch so mit foreach()

                Kommentar


                • #9
                  Danke für eure Inputs.

                  Ich frage mich zur Zeit noch wie ich das dann umsetzen soll. Das Query wird dann je nach dem recht kompliziert. Angenommen ich habe folgendes Ziel-Query:

                  "Select * from db_eventIndex WHERE ( "Select * from db_eventMembers WHERE userID = '$meineUserID ) and projectID = '$aktuellesProjekt' ORDER BY eventName ASC Limit 5, 10"

                  Wie baue ich ein solches Query in meiner Klasse zusammen?

                  Wenn ich nach OOP / PDO DB Klassen suche finde ich immer nur klassen bei welchen dann das Query ans Objekt geschickt wird. Ich will aber das Query ja innerhalb der Klasse zusammensetzen können in dem ich:

                  $meineklasse->setFilter('user', '$meineUserID');
                  $meineklasse->setFilter('project','$aktuellesProjekt');
                  $meineklasse->setOrder('eventName','asc');
                  $meineklasse->setLimit('5','10');
                  $meineklasse->getRows();

                  z.Bsp. diese Methoden aufrufe.

                  Oder ist dieser Ansatz bereits falsch? Kennt jemand eine gute Quelle zu dieser Thematik?

                  Mir ist ja schon klar dass ich Beispielsweise so vorgehen könnte:

                  PHP-Code:
                  class dbQuery() {

                    static function 
                  __construct(){
                       
                  $this->db = new dbClass();
                       
                  $this->sql "";
                  }

                   function 
                  setDatabase($db) {
                       
                  $this->sql .= "Select * from $db";
                  }

                   function 
                  setFilter($col$value){
                       
                  $this->sql .= "WHERE $col = $value";

                  etc. etc.

                  Aber wie flexibel ist das wirklich? Und vorallem gibt es einen besseren Weg?

                  Vielen Dank für eure Zeit!

                  eXe

                  Kommentar


                  • #10
                    Zitat von da.eXecutoR Beitrag anzeigen
                    Das Query wird dann je nach dem recht kompliziert. Angenommen ich habe folgendes Ziel-Query:

                    "Select * from db_eventIndex WHERE ( "Select * from db_eventMembers WHERE userID = '$meineUserID ) and projectID = '$aktuellesProjekt' ORDER BY eventName ASC Limit 5, 10"
                    Das könnte möglicherweise auch mit einem JOIN erreicht werden (keine Unterabfrage nötig)

                    Zitat von da.eXecutoR Beitrag anzeigen
                    Wie baue ich ein solches Query in meiner Klasse zusammen?
                    klingt nach einem Active Record Pattern (siehe Wikipedia, da sind auch entsprechende Links)

                    Zitat von da.eXecutoR Beitrag anzeigen
                    Wenn ich nach OOP / PDO DB Klassen suche finde ich immer nur klassen bei welchen dann das Query ans Objekt geschickt wird.
                    liegt wahrscheinlich daran, daß der Hauptzweck von PDO darin liegt, (fertige) SQL Anfragen an die DB zu schicken und die Ergebnisse bequem weiterzuverarbeiten. wie der Querystring ensteht, ist für PDO uninteressant.

                    Kommentar


                    • #11
                      Wenn ich mir den Wiki Artikel so durchlese fallen mir spontan zwei Sachen auf.

                      Erstens ist die Rede von Enterprise Lösungen... was meine webApp nicht gerade werden soll.

                      Und zweitens wird die Methode ja nicht gerade gerühmt.

                      Es wird aber ja wohl auch kaum die Lösung sein das Query prozedural zusammen zu bauen und dann über das db objekt die Abfrage laufen zu lassen.

                      Ich denke es wird doch sicher eine Lösung geben das ganze in OOP umzusetzen.

                      Wie löst ihr denn diese Situation? Hast du mal ein Beispiel? Bin ja sicherlich nicht der einzige der solche Querys zusammen stellen muss.

                      Grüsse

                      Kommentar


                      • #12
                        ich habe so wenige Queries, daß ich die noch per Hand schreiben kann. Ich konzentrierte mich bisher eher auf die Verarbeitung der Daten (z.B. foreach() anstatt while())

                        Kommentar


                        • #13
                          Zitat von da.eXecutoR Beitrag anzeigen
                          "Select * from db_eventIndex WHERE ( "Select * from db_eventMembers WHERE userID = '$meineUserID ) and projectID = '$aktuellesProjekt' ORDER BY eventName ASC Limit 5, 10"

                          Wie baue ich ein solches Query in meiner Klasse zusammen?
                          Mit ein paar Stringverknüpfungen und vielen IFs!?
                          PHP-Code:
                          $query  "    SELECT";
                          $query .= "        *";
                          $query .= "    FROM";
                          $query .= "        events";
                          if(
                          $this->user_id) {
                          $query .= "        INNER JOIN eventMembers USING (event_id)";
                          }
                          $query .= "    WHERE";
                          $query .= "        1";
                          if(
                          $this->user_id) {
                              
                          $query .= "    AND eventMembers.user_id = '$this->user_id'" 
                          }
                          if(
                          $this->project_id) {
                              
                          $query .= "    AND project_id = '$this->project_id'" 
                          }
                          if(
                          $this->order) {
                              
                          $query .= "ORBER BY $this->order";



                          Zitat von da.eXecutoR Beitrag anzeigen
                          Aber wie flexibel ist das wirklich? Und vorallem gibt es einen besseren Weg?
                          Für einzelne Tabellen ist es flexibel genug, aber wenn du viele Tabellen hast die in Relation stehen stößt man schnell an die Grenzen.
                          Und es gibt immer viele Wege. Die Frage ist was ist dein Ziel?

                          Kommentar


                          • #14
                            Zitat von da.eXecutoR Beitrag anzeigen
                            ...
                            Angenommen ich habe folgendes Ziel-Query:

                            "Select * from db_eventIndex WHERE ( "Select * from db_eventMembers WHERE userID = '$meineUserID ) and projectID = '$aktuellesProjekt' ORDER BY eventName ASC Limit 5, 10"

                            Wie baue ich ein solches Query in meiner Klasse zusammen?
                            Benutze einen Datenbanktreiber, der mit
                            prepared Statements umgehen kann. Die bieten so eine Art Platzhalter-Format, ähnlich wie sprintf(). Man schreibt die rohe Query-Anfrage mit Platzhaltern statt der echten Parameter in einen Format-String. Die einzelnen Parameter werden dann (bspw.) mit ->bindParam() dem (der?) Query hinzugefügt. Das verhindert gleichzeitig wirksam das Einschleusen von bösen Strings.

                            Zitat von erc Beitrag anzeigen
                            Mit ein paar Stringverknüpfungen und vielen IFs!?
                            PHP-Code:
                            // ...
                                
                            $query .= "    AND eventMembers.user_id = '$this->user_id'" 
                            }
                            if(
                            $this->project_id) {
                                
                            $query .= "    AND project_id = '$this->project_id'" 
                            }
                            if(
                            $this->order) {
                                
                            $query .= "ORBER BY $this->order";

                            Schon mal was von SQL-Injections gehört?

                            Kommentar


                            • #15
                              Zitat von fireweasel Beitrag anzeigen
                              Schon mal was von SQL-Injections gehört?
                              Ja und weiter?

                              Kommentar

                              Lädt...
                              X