Einbindung einer Datenbank in andere Klassen

Hi, also erstmal finde ich deine Lösung da ganz gut, ich benutze die Registry auch ganz gerne mal :)

Bei meiner Datenbankklasse (die eigentlich CMS_DB heisst) handelt es sich eigentlich um eine Factory Klasse und nicht um eine Datenbankabstraktion (wie z.B. in PEAR das DB oder MDB2 Paket), ich stelle also immer über diese Klasse die Datenbankverbindung her, allerdings kann ich halt über Parameter noch bestimmen welchen Datenbanktreiber ich benutzen will, also etwa so:

PHP:
class CMS_DB
{
  private static $_instances = array();

  private function __construct() { }

  public static function getInstance(array $pParams = null)
  {
    $id = '';

    if($pParams !== null)
    {
      foreach($pParams as $p)
      {
        $id .= $p;
      }
    }

    $id = md5($id);

    if(!isset(self::$_instances[$id]))
    {
      if($pParams === null)
      {
        $config = CMS_Config::getInstance();

        $class = 'CMS_DB_' . $config->db->type;
        $pParams = $config->db->getValues();

        if($config->db->type === null)
        {
          throw new CMS_DB_Exception('No database adapter specified');
        }
      }
      else
      {
        $class = isset($pParams['type']) ? 'CMS_DB_' . $pParams['type'] : null;

        if($class === null)
        {
          throw new CMS_DB_Exception('No database adapter specified');
        }
      }

      self::$_instances[$id] = new $class($pParams);

      CMS_Profiler::getInstance()->add("New database connection established");
    }

    return self::$_instances[$id];
  }
}
Als Datenbanktreiber benutze ich hauptsächlich PDO. Natürlich kann es manchmal sinnvoll sein eine erzeugte Datenbankverbindung zusätzlich in einer Registry Klasse zu speichern, da man ja nicht immer wieder alle Parameter bei getInstance() angeben will, allerdings brauche ich ja meist nur die Standardverbindung, die ich dann halt sehr bequem mit CMS_DB::getInstance() ohne Parameter erhalte.

Vielleicht inspiriert das ja den ein oder anderen, mal ein wenig mehr Ordnung ins allgemeine Klassenchaos zu bringen. ;)

P.S. Achja, ich benutze die __autoload() Funktion um die Klassen zu laden, desshalb fehlen include_once() bzw. require_once() Anweisungen im Code.

P.P.S. Bezüglich "den Namen kennen": Da hast du zwar recht, aber du musst ja auch überall den Namen deiner Registry kennen :D
 
Zuletzt bearbeitet:
P.P.S. Bezüglich "den Namen kennen": Da hast du zwar recht, aber du musst ja auch überall den Namen deiner Registry kennen :D
Naja, wenn ich in meinem Projekt meine Registry-Klasse habe, kann man eigentlich davon ausgehen, dass diese gleich bleibt, bzw. keine großen Änderungen an ihr vorgenommen werden, da das Registry-Pattern ja quasi "vorgegeben" ist.

Gehen wir mal davon aus, du benutzt nicht deine eigene Datenbankklasse sondern irgendeine Andere.
Irgendwann merkst du, dass diese Datenbankklasse deinen Anforderungen nicht entspricht und du möchtest sie wecheln.

Du müsstest dann in allen Klassen den Aufruf:
PHP:
$db = Alte_DB_Klasse::get_instance($parameter);
in:
PHP:
$db = Neue_DB_Klasse::get_instance($andereParameter);
ändern.
Bei der Registry müsstest du hier nur die Instanzierung vor der Registrierung anpassen.

Aber das hängt auch stark vom Projekt ab. In deinem Fall hast du es ja gut gelöst! ;-)

Zudem ist das ja auch mehr oder weniger nur Haarspalterei und jeder sollte selbst entscheiden was für ihn am besten geeignet ist. :)
 
Ich möchte wirklich keine Haarspalterei anfangen, allerdings ist glaube ich das Konzept hinter meiner DB Klasse nicht gut rüber gekommen. Die Klasse CMS_DB stellt keine Datenbankverbindung her und ist auch (bis auf ein paar Konstanten) hier vollständig aufgeführt. Sie hat nur diese eine statische Methode getInstance(), die anhand der ihr übergebenen Parameter automatisch die passende Datenbankklasse lädt, sie instanziert und als Referenz zurückgibt. Es besteht also nie (!) die Notwendigkeit auch nur eine einzige Zeile ausserhalb der Klasse zu ändern, es sei denn, die neue Datenbankklasse hat andere Zugriffsmethoden.

Die Methode holt sich, falls keine Parameter angegeben sind, automatisch die Informationen aus der Konfigurationsdatei, eine Änderung in dieser Datei genügt also, um die Standardklasse und die Verbindungsdaten zu wechseln.

Die Parameter der Methode sind ein array, desshalb können sie nach Belieben weggelassen werden. Wenn ich z.B. eine MySQL Verbindung brauche, dann kann ich das so lösen:
PHP:
$params = array
(
  'type' => 'mysql',
  'host' => 'localhost',
  'user' => 'username',
  'password' => 'password',
  'db' => 'DB Name'
);

$db = CMS_DB::getInstance($params);
Will ich nun auf eine Oracle Datenbank wechseln, brauche ich halt nur das $params Array anzupassen indem ich 'type' auf 'oci8' setze und die anderen Daten anpasse.

Natürlich kann man dann die konkrete Datenbankklasse ($db) in einer Registry speichern, $db ist jedoch nie vom Typ CMS_DB (!), denn die Klasse CMS_DB erstellt lediglich die konkrete Klasse und gibt sie zurück.

P.S. War jetzt vielleicht doch ein bisl Haarspalterei, aber ich will ja nich behaupten, dass meine Lösung besonders gut, oder andere Lösungen besonders schlecht sind, sondern nur mal versuchen, zu zeigen, warum ich diese Lösung gewählt habe. Ich finde übrigens, dass beide Ansätze (Factory und Registry) kombiniert am besten sind, vor allem, wenn man viele verschiedene Datenbankverbindungen braucht, ein Vorteil meiner Methode ist jedoch, dass die Datenbank erst wenn sie wirklich gebraucht wird instanziert wird.
 
Zuletzt bearbeitet:
Ich glaube du hast da was überlesen:
Gehen wir mal davon aus, du benutzt nicht deine eigene Datenbankklasse sondern irgendeine Andere.
Irgendwann merkst du, dass diese Datenbankklasse deinen Anforderungen nicht entspricht und du möchtest sie wecheln. (...)
;)

Ich hab das Beispiel nur aufgeführt, weil ich in meinem Fall kein eigenes Datenbanksystem benutze und deshalb auf das Registry-Pattern zurückgreife, um es mir einfach zu machen, zwischen verschiedenen Datenbanksystemen zu wechseln! :)
 
Ja, das habe ich auch so verstanden, ich wollte nur mal zeigen, dass das mit meiner Klasse auch ohne Probleme geht. Man muss dann halt nur die CMS_DB::getInstance() Methode umschreiben, um eine andere Datenbankklase zu instanzieren. Der Vorteil dabei ist dann aber, dass man im Array $params immer die gleichen Indizes benutzen kann, also die Verbindung "von außen" immer die gleichen Parameter zum verbinden nutzen kann, unabhängig von der verwendeten Klasse.
 
Achso, dann habe ich das wohl falsch interpretiert. :suspekt:

Dann ist dieses Thema bis auf weiteres erstmal erledigt!
 
Zurück