tutorials.de Buch-Aktion 05/2012
ERLEDIGT
NEIN
ANTWORTEN
7
ZUGRIFFE
958
EMPFEHLEN
  • An Twitter übertragen
  • An Facebook übertragen
AUF DIESES THEMA
ANTWORTEN
  1. #1
    Lunatic Tutorials.de Gastzugang
    Hallo liebe tutorials.de Community,

    eine Sache vorweg, ich habe bereits gegoogled aber keine zufriedenstellende Lösung gefunden.

    Es geht um folgendes:
    Ich habe eine User Klasse. Die hält verschiedene Methoden bereit, z.B. selectUser($id), getUserData($key) etc...
    u.a habe ich allerdings auch noch eine MySQL Klasse für Dinge die eine MySQL Klasse eben braucht. Queries, Fetching etc...

    In der index.php lade ich erstmal die benötigten Klassen und instanziere sie dann:

    PHP-Code:
    $mysql = new MySQL('localhost''user''pass''db');
    $core = new Core();
    $user = new User();
    echo 
    $user->selectUser(1); 
    Soa, dass wäre das Debakel. Die selectUser Methode ruft eine Methode der mySQL Klasse auf. Die Instanz der MySQL Klasse ist in der User Klasse allerdings nicht gültig weshalb ich die "call to a member function" Fehlermeldung erhalte.

    Denkbare Möglichkeiten wären nun eben entweder die MySQL Klasse als Referenz zu übergeben, in jede Methode der Userklasse ein global $mysql; zu bomben oder die MySQL Klasse statisch zu machen. Darüber hinaus könnte ich die MySQL Klasse statisch machen. Allerdings misfallen mir aber alle o.g. Möglichkeiten und von ein paaren habe ich auch schon mitgekriegt, sie seien unsauber.

    Meine Frage wäre nun, wie sähe denn eine saubere Möglichkeit aus die MySQL Klasse in der User- und ggf. noch anderen Klassen verfügbar zu machen?
    Ich danke schonmal im Voraus,
    Lunatic
     

  2. #2
    Avatar von saftmeister
    saftmeister saftmeister ist offline Der Saft sei mit dir
    tutorials.de Premium-User
    Registriert seit
    May 2006
    Ort
    There is no place like 127.0.0.1
    Beiträge
    3.521
    Du findest Singletons unsauber? Ich würde es darüber erledigen. Ist ganz einfach zu implementieren und beschleunigt wahrscheinlich sogar deinen Code etwas. Du brauchst deine Klasse MySQL noch nicht mal anpassen. Du abstrahierst sie einfach:

    Code php:
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    
    class Database extends MySQL
    {
      private static $_instance;
     
      public static function getInstance()
      {
         if( self::$_instance == null )
         {
           self::$_instance = new Database('localhost', 'user', 'pass', 'db');
         }
         return self::$_instance;
      }
    }

    Jetzt fragst du dich vielleicht, warum das deinen Code beschleunigen soll. Weil du immer nur eine Instance von MySQL (bzw. Database) hast. Das ganze verwendest du dann so:

    Code php:
    1
    2
    3
    4
    
    $user = Database::getInstance()->query("SELECT * FROM users WHERE id = " . $userid);
    $userdetails = Database::getInstance()->query("SELECT * FROM userdetails WHERE userdetailid = " . $user->detailid);
     
    // usw. usf.

    Was daran unsauber sein soll, verstehe ich noch nicht ganz. Es gibt zwar eine Methode, bei der bewiesen werden kann, das ein Singleton nicht immer ein Singleton ist, aber das ist bei PHP so gut wie unmöglich anzuwenden, da PHP in sich nicht threaded ist. Wenn man aber auf Nummer sicher gehen will, implementiert man in ein Singleton auch noch Mutexes. Dann hat man prinzipiell gesehen sogar die Critical-Sections-Implementierung von Java implementiert.
     
    Grüße
    --
    Qualität des Codes wird in WTF's/Min gemessen: Je mehr, desto schlechter der Code ;-)

  3. #3
    Avatar von bn
    bn bn ist offline Mitglied Brokat
    Registriert seit
    Oct 2002
    Ort
    Berlin
    Beiträge
    395
    Kann mich Saftmeister nur anschließen. Das Singleton Pattern bietet sich insbesondere bei Datenbank Instanzen an.

    Grüße BN
     

  4. #4
    Lunatic Tutorials.de Gastzugang
    Kann mich Saftmeister nur anschließen. Das Singleton Pattern bietet sich insbesondere bei Datenbank Instanzen an.
    Wenn man die Verbindung zu nur einer Datenbank gleichzeitig herstellen will...
     

  5. #5
    Avatar von saftmeister
    saftmeister saftmeister ist offline Der Saft sei mit dir
    tutorials.de Premium-User
    Registriert seit
    May 2006
    Ort
    There is no place like 127.0.0.1
    Beiträge
    3.521
    Zitat Zitat von Lunatic Beitrag anzeigen
    Wenn man die Verbindung zu nur einer Datenbank gleichzeitig herstellen will...
    Hast du das so vor? Also mehrere Instanzen zu verschiedenen Datenbank aufbauen? Wenn ja, hast du ein kleines aber wichtiges Detail unterschlagen. In der Tat wäre mein Vorschlag dann nicht anwendbar.
     
    Grüße
    --
    Qualität des Codes wird in WTF's/Min gemessen: Je mehr, desto schlechter der Code ;-)

  6. #6
    Avatar von ComFreek
    ComFreek ComFreek ist gerade online [x] Let it be logic!
    tutorials.de Moderator
    Registriert seit
    Jun 2009
    Beiträge
    2.364
    Blog-Einträge
    4
    Du könntest auch das globale Array $GLOBALS verwenden:
    PHP-Code:
    $GLOBALS['DB'] = new MySQL('localhost''user''pass''db'); 

    public function 
    selectUser($id)
    {
      
    $GLOBALS['DB']->Query("...");

     
    mfg ComFreek

    Falls ich dir geholfen habe, würde ich mich über ein DANKE freuen!
    Kenn mich am besten aus in C++, WEB-Sprachen (PHP, HTML, JavaScript) und vllt. mehr
    [PHP] Überprüfen, ob Website erreichbarSicherheit in PHP-Codes schaffenGoogle Chrome-Extension für tutorials.dejson_compress()

  7. #7
    Avatar von zer0
    zer0 zer0 ist offline Mitglied Brokat
    Registriert seit
    Oct 2009
    Beiträge
    323
    Wie wäres es den mit dem Registry-Pattern: Registry

    In deiner index.php oder in deinem Core, wo die Datenbankverbdindung aufbaust setzt du sie in die Registry. Nun kannst du in jeder Datei wo du eine Verbindung brauchst sie abfragen.

    So etwa:
    Code PHP:
    1
    2
    3
    4
    5
    6
    7
    8
    
        try {
            $db = new PDO($dsn, $user, $password, $attributes);
        } catch(PDOException $e) {
            echo "An exception occured while trying to connect to Database. Error: ".$e->getMessage();
        } 
     
        // Datenbank registrieren
        Registry::set('db', $db);

    Und dann in den Dateien/Klassen wo du sie brauchst:
    Code PHP:
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    
        class Model {
     
            private static $db = null;
     
            public static function getDB() {
                self::$db = Registry::get('db');
                return self::$db;
            }
     
            public static function getUser($id) {
                $stmt = self::getDB()->prepare("SELECT * FROM user WHERE ID=:id");
                $stmt->bindParam(':id', $id);
                $stmt->execute();
                
                return $stmt->fetch();
            }
        }

    Das wars!
     

  8. #8
    Avatar von bn
    bn bn ist offline Mitglied Brokat
    Registriert seit
    Oct 2002
    Ort
    Berlin
    Beiträge
    395
    Zitat Zitat von Lunatic Beitrag anzeigen
    Wenn man die Verbindung zu nur einer Datenbank gleichzeitig herstellen will...
    sagt wer?

    Konfigurations-Klasse (kannste auch anders und ohne Klasse machen, ich möchte es nur andeuten):
    PHP-Code:
    class DbConfig 
    {
        
    /**
         * KonfigurationsArray
         * @var array $dbConfigs
         */
        
    private static $dbConfigs = array (
            
    'db0' => array (
                
    'user' => 'root',
                
    'pass' => '',
                
    'host' => 'localhost',
                
    'port' => 3306,
                
    'dba'  => 'database1'
            
    ),
            
    'db1' => array (
                
    'user' => 'root',
                
    'pass' => '',
                
    'host' => 'andererhost',
                
    'port' => 3306,
                
    'dba'  => 'database39'
            
    )
        );
        
        
    /**
         * Getter
         * @param string $instanceName
         * @return array
         */
        
    public static function get ($instanceName)
        {
            if (!isset (
    self::$dbConfigs [$instanceName]))
            {
                
    // Exception werfen oder andere Fehlerbehandlung...
            
    }
            
            return 
    self::$dbConfigs [$instanceName];
        }

    angedeutete Datenbank-Klasse (Singleton auch für mehrere Connections):
    PHP-Code:
    class MyDatabase
    {
        
    /**
         * Intanzholder
         * @var array
         */
        
    private static $instances = array ();
        
        
    /**
         * Getter für Datenbankinstanz
         * @param string $instanceName
         * @return MyDatabase
         */
        
    public static function getInstance ($instanceName)
        {
            if (!isset (
    self::$instances [$instanceName]))
            {
                
    self::$instances [$instanceName] = new MyDatabase ($instanceName);
            }
            
            return 
    self::$instances [$instanceName];
        }
        
        
    /**
         * Konstruktor
         * nicht public aufrufbar, da nur über getInstance instanzierbar
         * @param string $instanceName
         */
        
    private function __construct ($instanceName)
        {
            
    $this->connect (DbConfig::get ($instanceName));
        }
        
        
    /**
         * Verbindungsaufbau
         * @param array Verbindungsparameter
         */
        
    private function connect ($dbConfig)
        {
            
    // mysql connection ...
            
    print_r ($dbConfig);
        }

    kleiner Test:
    PHP-Code:
    MyDatabase::getInstance ('db0');
    MyDatabase::getInstance ('db0');
    MyDatabase::getInstance ('db0');
    MyDatabase::getInstance ('db1');
    MyDatabase::getInstance ('db0');
    MyDatabase::getInstance ('db1');
    MyDatabase::getInstance ('db0'); 
    Du bekommst lediglich 2x die Parameter gepromptet. Der Code ist so nicht zu verwenden, da Exceptions/Fehlerbehandlungen fehlen und auch sonst nützliche Dinge. Aber das erklärt sich von selbst. Dein Argument "geht nicht" zählt also nicht. Mit GLOBAL-Gedöns würde ich gleich mal gar nicht arbeiten. Das ist zwar schön einfach aber auch schön hässlich.

    Grüße BN
     

Ähnliche Themen

  1. Innerhalb einer Klasse eine Instanz einer anderen Klasse
    Von HackerNeo im Forum VisualStudio & MFC
    Antworten: 1
    Letzter Beitrag: 17.11.09, 13:08
  2. Antworten: 3
    Letzter Beitrag: 18.12.07, 15:38
  3. Antworten: 2
    Letzter Beitrag: 30.03.06, 20:40
  4. Variable aus CMainFrame in anderer Klasse verwenden
    Von PascalRode im Forum VisualStudio & MFC
    Antworten: 5
    Letzter Beitrag: 19.08.04, 01:17
  5. Antworten: 4
    Letzter Beitrag: 28.10.02, 00:47