Ankündigung

Einklappen
Keine Ankündigung bisher.

eigene MySQLi-Klasse verschiedene Verbindungen

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

  • eigene MySQLi-Klasse verschiedene Verbindungen

    Hallo zusammen,
    ich bin momentan dabei mich in OOP zu versuchen und stelle dazu eine existierende Website um.
    Ich habe mir folgende Database.php zusammengebastelt:
    PHP-Code:
    <?php

    class Database {

        private static 
    $db;
        private 
    $connection;

        public function 
    __construct($connect) {
            require_once(
    'Session.php');
            require_once(
    'Config.php');
            new 
    Config();

            
    $möglich = array('mgl1','mgl2''mgl3','mgl4','mgl5'null);

            if(!
    in_array($connect$möglich)) {
                exit();
            }
            else {
                
    $loginInfo Config::getLoginData($connect null);

                
    $this->connection = new MySQLi($loginInfo[0], $loginInfo[1], $loginInfo[2], $loginInfo[3]);
                if(
    $this->connection -> connect_errno) { printf("Connection failed! %s\n"$this->connection -> connect_error); exit(); }
                
    mysqli_select_db($this->connection$loginInfo[3]) or DIE('Database name is not available!');

                if(
    $connect == null) {
                    
    mysqli_query($this->connection"UPDATE `admins` SET `zuletzt` = NOW() WHERE `Name` = '".Session::get('userName')."'");
                    
    mysqli_query($this->connection"UPDATE `admins` SET `angemeldet` = '0' WHERE `angemeldet` = '1' AND (TIMESTAMPDIFF(MINUTE, `zuletzt`, NOW()) >= 15)");
                }
            }
        }

        public function 
    __destruct() {
            
    $this->connection->close();
        }

        public function 
    query($query) {
            
    $conn self::getConnection();
            
    $ret mysqli_query($conn$query);
            if(!
    $ret) {
                
    $ret mysqli_error($conn);
            }
            return 
    $ret;
        }

        public function 
    getResult($query) {
            return 
    mysqli_fetch_assoc($query);
        }

        public function 
    update($query) {
            
    $conn self::getConnection();
            
    mysqli_query($conn$query);
        }

        public function 
    prepare($input) {
            
    $conn self::getConnection();
            
    $ret mysqli_real_escape_string($conn$input);
            return 
    $ret;
        }

        private static function 
    getConnection() {
            if (
    self::$db == null) {
                
    self::$db = new Database();
            }
            return 
    self::$db->connection;
        }
    }

    ?>
    Allerdings ist ja nach neuem erzeugen der Klasse self::$db immer null, weshalb in der 5. Zeile von unten ja auch self::$db = new Database(); ausgeführt wird. Da ich aber (wie oben vielleicht erkennbar) nicht nur eine Verbindung einbauen möchte sondern auch unterschiedliche Verbindungen aufbauen will, funktionieren die anderen natürlich nicht, da dann immer __construct($connect = null) ausgeführt wird.
    Ich möchte in anderen Dateien quasi gleichzeitig zwei Verbindungen offen haben. Kann mir da jemand auf die Sprünge helfen? Und wie erwähnt, ich bin in OOP noch Anfänger, also bitte möglichst einfach erklären. Achja, obige Datei ist noch nicht ganz auf OOP umgestellt.


  • #2
    Du hast da ein Singleton-Pattern implementiert. Da du mehrere Datenbankverbindungen möchtest ist das falsch.
    Eine static Variable (wie die $db) ist für die komplette Klasse gültig und unabhängig von Objekten. Deshalb hält diese auch immer nur das Verbindungs-Objekt der zuletzt erzeugten Instanz.

    Um mehrere Verbindungen herzustellen instanzierst du die Klassen mehrmals. Im Objekt (also als Attribut) hälst du pro Verbindung das Verbindungs-Objekt und erzeugst das Objekt auch über den Konstruktur direkt (nicht über getConnection).
    "Software is like Sex, it's best if it's free." - Linus Torvalds

    Kommentar


    • #3
      Zitat von JaMa Beitrag anzeigen
      Du hast da ein Singleton-Pattern implementiert. Da du mehrere Datenbankverbindungen möchtest ist das falsch.
      Eine static Variable (wie die $db) ist für die komplette Klasse gültig und unabhängig von Objekten. Deshalb hält diese auch immer nur das Verbindungs-Objekt der zuletzt erzeugten Instanz.

      Um mehrere Verbindungen herzustellen instanzierst du die Klassen mehrmals. Im Objekt (also als Attribut) hälst du pro Verbindung das Verbindungs-Objekt und erzeugst das Objekt auch über den Konstruktur direkt (nicht über getConnection).
      Heißt, ich schmeiß das hier
      PHP-Code:
       if (self::$db == null) {
                  
      self::$db = new Database($connect);
              } 
      so in den Konstruktor, und dann sollte es gehen? kann ich die funktion getConnection dann löschen und die restlichen Aufrufe anpassen?

      Kommentar


      • #4
        Nein, du solltest keine statische Variable verwenden.

        Und übrigens solltest du auch kein require_once() verwenden. Um Klassen zu laden wurde der Autoloader erfunden.

        Kommentar


        • #5
          Zitat von hellbringer Beitrag anzeigen
          Nein, du solltest keine statische Variable verwenden.

          Und übrigens solltest du auch kein require_once() verwenden. Um Klassen zu laden wurde der Autoloader erfunden.
          Genau da war ja die Frage, wie münze ich das genau um, damit das läuft? Es wird ja kaum reichen, $db in eine nicht-statische Variable zu ändern und den Rest zu lassen, oder?

          Kommentar


          • #6
            Zitat von JohnHSmith Beitrag anzeigen
            Genau da war ja die Frage, wie münze ich das genau um, damit das läuft? Es wird ja kaum reichen, $db in eine nicht-statische Variable zu ändern und den Rest zu lassen, oder?
            Die statische Zugriffe musst du natürlich auch in nichtstatische ändern.

            Kommentar


            • #7
              Zitat von hellbringer Beitrag anzeigen

              Die statische Zugriffe musst du natürlich auch in nichtstatische ändern.
              Okay, aber new Database() erstellt doch trotz allem eine neue Instanz der Klasse mit null-argument. Oder lösch ich das dann komplett?

              Kommentar


              • #8
                Zitat von JohnHSmith Beitrag anzeigen

                Genau da war ja die Frage, wie münze ich das genau um, damit das läuft? Es wird ja kaum reichen, $db in eine nicht-statische Variable zu ändern und den Rest zu lassen, oder?
                Schmeiß die $db und getConnection raus und instanziere deine Datenbankverbindungen:
                PHP-Code:
                $dbConn1 = new Database("db1");
                $dbConn2 = new Database("db2"); 
                Desweiteren solltest du die die Config und Session (wofür auch immer) Objekte injecten (Constructor-Injection), damit fallen auch die require_once im Constructor raus und du hast keine statischen Abhängigkeiten.
                Außerdem keine Umlaute in Variablennamen nutzen ($möglich).

                EDIT:

                Sorry, die self::getConnection() änderst du natürlich um auf $this->connection;
                "Software is like Sex, it's best if it's free." - Linus Torvalds

                Kommentar


                • #9
                  Zitat von JaMa Beitrag anzeigen

                  Schmeiß die $db und getConnection raus und instanziere deine Datenbankverbindungen:
                  PHP-Code:
                  $dbConn1 = new Database("db1");
                  $dbConn2 = new Database("db2"); 
                  Desweiteren solltest du die die Config und Session (wofür auch immer) Objekte injecten (Constructor-Injection), damit fallen auch die require_once im Constructor raus und du hast keine statischen Abhängigkeiten.
                  Außerdem keine Umlaute in Variablennamen nutzen ($möglich).

                  EDIT:

                  Sorry, die self::getConnection() änderst du natürlich um auf $this->connection;
                  Die Injections setze ich via extends soweit ich das verstanden habe, oder?

                  Kommentar


                  • #10
                    Was sind "extends"?

                    Kommentar


                    • #11
                      Zitat von hellbringer Beitrag anzeigen
                      Was sind "extends"?
                      Okay, offenbar hab ich nicht recht. ich dachte da an etwas wie class User extends User2 oder sowas...
                      Bitte, belehre mich eines besseren, wie ich hier diese Constructor-Injections verwende.

                      Kommentar


                      • #12
                        Ohje, nein ...
                        Du solltest dir dringend nochmal Grundlagen der Objektorientierten Programmierung zu Gute führen.

                        "extends" ist für die Vererbung.

                        Mit Constructor-Injection meine ich:

                        PHP-Code:
                        class Database
                        {
                        private 
                        $config;
                        public function 
                        __constructor (Config $config) {
                        $this->config $config;
                        }
                        }

                        ...
                        $config1 = new Config();
                        $dbConn1 = new Database($config1); 
                        Sollte die Config Klasse nicht nur eine DatenbankConfig-Klasse sein (was ich vermute), dann ist obiges auch nicht optimal, da das Datenbankobjekt selbst wissen müsste wie es sich zu erstellen hat (welche Werte aus Config).
                        Stattdessen müsstest du dann die benötigten Werte übergeben (Host, User, Password, etc.) oder ein spezielles DatenbankConfig-Objekt.
                        "Software is like Sex, it's best if it's free." - Linus Torvalds

                        Kommentar


                        • #13
                          Nein, die Config-Klasse beinhaltet mehrere funktionen. Die SQL-Daten lade ich aus einer .config datei und füge sie einem array hinzu. Dieses array wird returned.

                          Kommentar


                          • #14
                            Zitat von JaMa Beitrag anzeigen
                            Ohje, nein ...
                            Du solltest dir dringend nochmal Grundlagen der Objektorientierten Programmierung zu Gute führen.

                            "extends" ist für die Vererbung.

                            Mit Constructor-Injection meine ich:

                            PHP-Code:
                            class Database
                            {
                            private 
                            $config;
                            public function 
                            __constructor (Config $config) {
                            $this->config $config;
                            }
                            }

                            ...
                            $config1 = new Config();
                            $dbConn1 = new Database($config1); 
                            Sollte die Config Klasse nicht nur eine DatenbankConfig-Klasse sein (was ich vermute), dann ist obiges auch nicht optimal, da das Datenbankobjekt selbst wissen müsste wie es sich zu erstellen hat (welche Werte aus Config).
                            Stattdessen müsstest du dann die benötigten Werte übergeben (Host, User, Password, etc.) oder ein spezielles DatenbankConfig-Objekt.
                            So, ich habe jetzt mal eine autoLoader-klasse erstellt. Diese sieht so aus:
                            PHP-Code:
                            <?php

                            class autoLoader {
                                public function 
                            __construct() {
                                    
                            spl_autoload_register(array($this'load_class'));
                                }

                                public static function 
                            register() {
                                  new 
                            autoLoader();
                                }

                                public function 
                            load_class($class_name) {
                                    
                            $file 'requirements/'.strtolower(str_replace('\\','/',$class_name)).'.php';
                                    if(
                            file_exists($file)) {
                                        require_once(
                            $file);
                                    }
                                }
                            }

                                
                            Autoloader::register();


                                new 
                            Session();
                                
                            $DB1 = new Database('mgl1');
                                
                            $DB2= new Database("mgl2");
                                
                            $DB3= new Database("mgl3");
                                
                            $DB4= new Database("mgl4");
                                new 
                            User();
                                new 
                            Config();

                            ?>
                            Diese Datei hole ich mir via require_once('requirements/autoLoader.php'); in meine index.php.
                            Da gibt er mir allerdings dann den Fehler aus:
                            Notice: Undefined variable: DB1 in [...]\requirements\User.php on line 42
                            Diese Zeile lautet
                            $var= $DB1->prepare($Name);
                            Also wird $DB1 nicht richtig gesetzt. Fehlermeldung wird aber sonst keine ausgegeben, Zugangsdaten sind also korrekt. Wieso kennt er die Variable denn nicht, wenn beide doch required sind?

                            Kommentar


                            • #15
                              Nachdem du die Datei User.php geheim hältst, kann ich dir auch nicht sagen, wo hier der Fehler ist.

                              Übrigens macht ein alleinstehendes new Session(), new User(), usw. keinen Sinn. Du solltest das erstellte Objekt schon einer Variable zuweisen, wie sonst willst du das Objekt verwenden?

                              Kommentar

                              Lädt...
                              X