Portal > Foren > PHP > PHP-Programmierung > Probleme mit Singelton u. PDO
Antwort
 
Themen-Optionen Thema durchsuchen
Alt 01.03.2008, 21:14 Nach oben    #1
Neuer Benutzer
 
Registriert seit: 17.09.2006
Beiträge: 6
Standard Probleme mit Singelton u. PDO

Hallo liebe Community,

Sorry, wenn ich vielleicht nun eine schwachsinnige Frage stelle.
In den Methoden soll eine DB-Zugriff gestattet sein.

Möglich sei : global $pdo;
Jedoch soll global unsauber sein und ich hab es nun über Singleton versucht.
Dabei muss ich ehrlich sein, dass ich mich erst seit heute damit befasse .
Dabei treten wohl einige Probleme und Denkfehler auf.

PHP-Code:
class Singleton
{
    
/**
      * Klassen-Variablen
     * 
      * @author  Jan Steiger
      * @version 01.03.2008, 18:17 Uhr
      * 
      * @var     $instance
      */
    
private static $instance Null;
    
    
/**
      * Konstruktor von Singleton, erstellen
     * 
      * @author  Jan Steiger
      * @version 01.03.2008, 18:21 Uhr
      */
    
protected function __construct(){}
    
    
/**
      * Klon-Methode
     * 
      * @author  Jan Steiger
      * @version 01.03.2008, 18:21 Uhr
      */
    
private final function __clone(){}
    
    
/**
      * Übergabe, der Instance
     * 
      * @author  Jan Steiger
      * @version 01.03.2008, 18:23 Uhr
      * 
      * @return  $instance;
      */
    
public static function getInstance($class)
    {
        if(
self::$instance === Null)
        {
            
self::$instance = new $class;
        }
        
        return 
self::$instance;
    }
}

------------- 
PDO ----

class 
SPDO extends PDO
{
    
/**
      * Klassen-Variablen
     * 
      * @author  Jan Steiger
      * @version 01.03.2008, 18:30 Uhr
      * 
      * DB-Login, Konstanten
      */
    /**
     const LOCAL  = 'localhost';
     const DBUSER = 'root';
     const DBPASS = '';
     const DBNAME = 'kerb';
    **/
    /**
      * SPDO-Konstuktor
     * 
      * @author  Jan Steiger
      * @version 01.03.2008, 18:33 Uhr
      * 
      * 
      */
    
public function __construct(){}
    
    public function 
connect()
    {
        try
        {
            new 
PDO("mysql:host=".'localhost'.";dbname=".'kerb'.""'root''');
        }catch(
PDOExCeption $e )
        {
            print 
'Error!: '.$e->getMessage().' <br />'
            die();
        }
            
    }
    
//$SPDO = new PDO("mysql:host=".self::LOCAL.";dbname=".self::DBNAME."", self::DBUSER, self::DBPASS);
        
}

---------- 
TEST.php ---------
require_once(
'inc/module/singleton.inc.php');
require_once(
'inc/db/pdo.inc.php');

$SPDO = &Singleton::getInstance('SPDO');
$SPDO->connect();



// Aktuelle-Nachricht aus Datenbank-holen
        
$dbnews $SPDO->prepare("SELECT `topic`, `datum`, `id` 
                          FROM     `news`
                          WHERE  `status` = '1'
                          ORDER BY `id` ASC
                          LIMIT 1"
);
        
$dbnews ->execute();
        

        
$news      $dbnews->fetch(PDO::FETCH_ASSOC); 
Warning: PDO:repare() [function.PDO-prepare]: SQLSTATE[00000]: No error: PDO constructor was not called in D:\xampp\htdocs\cms\test.php on line 33

Fatal error: Call to a member function execute() on a non-object in D:\xampp\htdocs\cms\test.php on line 34

Ich sitze seit ein paar Std. dran und ich komm nicht auf den Nenner.
Vielleicht könnt ihr meine Fehler erklären
Beckham ist offline  
Diesen Beitrag zu to del.icio.us hinzufügen!Diesen Beitrag zu Technorati hinzufügen!Diesen Beitrag zu Mister Wong hinzufügen!
Mit Zitat antworten
Alt 01.03.2008, 22:04 Nach oben    #2
Bastian Fenske
 
Registriert seit: 04.01.2006
Ort: Kassel
Beiträge: 867
Standard

Hi „Beckham“ (oder Jan?).

Du musst die Klasse selbst (also SPDO) als Singleton umsetzen. Du machst aus einer Klasse ein Singleton, um zu verhindern, dass es zur Laufzeit mehrfach instanziert wird. Daher muss eben die Klasse selbst ein Singleton sein. Ein Singleton ist also keine Fabrik, die dir ein Objekt einer anderen Klasse baut.

Pack also die getInstance()-Methode in SPDO, entferne darin den $class-Parameter und ersetze new $class darin durch new SPDO. Auch die __clone()-Methode verschiebst du in SPDO und machst dort den Konstruktor privat.

Siehe z.B. hier:
Singleton-Beispiel

Verwirrend auch hier vielleicht wieder die Bezeichnung „Singleton“ dieser Klasse. Nimm also z.B. diese Klasse (bzw. deine liegt ja nur knapp daneben), benenne sie in SPDO um und erweitere den Code.

Eine abstrakte Singleton-Klasse macht in PHP wenig Sinn, da sich aus einer statischen Methode nur der Klassenname der (abstrakten) Klasse selbst auslesen lässt, nicht jedoch der Name der Klasse, über die die (geerbte) Methode dann aufgerufen wurde.

Diskussion dazu z.B. hier:
Late Static Binding in PHP

Basti

Geändert von Basti (01.03.2008 um 22:10 Uhr)
Basti ist offline  
Diesen Beitrag zu to del.icio.us hinzufügen!Diesen Beitrag zu Technorati hinzufügen!Diesen Beitrag zu Mister Wong hinzufügen!
Mit Zitat antworten
Alt 01.03.2008, 22:24 Nach oben    #3
Neuer Benutzer
 
Registriert seit: 17.09.2006
Beiträge: 6
Standard

Den Konstruktor hab ich als private gekennzeichnet, doch er gibt mir einen Fehler aus.

Fatal error: Access level to SPDO::__construct() must be public (as in class PDO) in D:\xampp\htdocs\cms\inc\db\pdo.inc.php on line 86

Sonst hab ich soweit alles ausgebessert
Beckham ist offline  
Diesen Beitrag zu to del.icio.us hinzufügen!Diesen Beitrag zu Technorati hinzufügen!Diesen Beitrag zu Mister Wong hinzufügen!
Mit Zitat antworten
Alt 02.03.2008, 01:24 Nach oben    #4
Bastian Fenske
 
Registriert seit: 04.01.2006
Ort: Kassel
Beiträge: 867
Standard

Ja, du kannst eine Klasse nicht „dichter“ machen, indem du von ihr ableitest. Wenn also PDO einen öffentlichen Konstruktor hat, muss SPDO das auch haben. Musst dann eben anders verhindern, dass dieser mehrfach aufgerufen wird, z.B. so:
PHP-Code:
<?php

class SPDO
{
    private static 
Instance;

    public function 
__construct()
    {
        if (!
is_null(self::$Instance))
            throw new 
Exception('...');

        
self::$Instance $this;

        
parent::__construct();
    }

    public static function 
getInstance()
    {
        if (!
is_null(self::$Instance))
            new 
SPDO();

        return 
self::$Instance;
    }

    private function 
__clone() {}
}
…schöner ist es aber sicher, die Klasse einmal von außen zu bauen und nicht on demand. Macht bei einer solchen Klasse ja auch Sinn, da die Konfigurations-Parameter braucht. also eher sowas:


PHP-Code:
<?php

class SPDO
{
    private static 
Instance;

    public function 
__construct(Config $Config)
    {
        if (!
is_null(self::$Instance))
            throw new 
Exception('Singleton!');

        
self::$Instance $this;

        
parent::__construct($Config);
    }

    public static function 
getInstance()
    {
        if (
is_null(self::$Instance))
            throw new 
Exception('has not been built yet');

        return 
self::$Instance;
    }

    private function 
__clone() {}
}
Basti
Basti ist offline  
Diesen Beitrag zu to del.icio.us hinzufügen!Diesen Beitrag zu Technorati hinzufügen!Diesen Beitrag zu Mister Wong hinzufügen!
Mit Zitat antworten
Alt 02.03.2008, 09:26 Nach oben    #5
Neuer Benutzer
 
Registriert seit: 17.09.2006
Beiträge: 6
Standard

Es funktioniert soweit

So wie ich das sehe muss ich : $SPDO = SPDO::getInstance();
immer wieder in die Methode mit einbauen.

Damit eine Verbindung möglich ist.
Gibt es keine Lösung dazu einmal die $SPDO = SPDO::getInstance();

anzuwenden, damit Sie überall anwendbar ist?
Beckham ist offline  
Diesen Beitrag zu to del.icio.us hinzufügen!Diesen Beitrag zu Technorati hinzufügen!Diesen Beitrag zu Mister Wong hinzufügen!
Mit Zitat antworten
Alt 02.03.2008, 12:56 Nach oben    #6
Bastian Fenske
 
Registriert seit: 04.01.2006
Ort: Kassel
Beiträge: 867
Standard

Zitat:
Zitat von Beckham Beitrag anzeigen
So wie ich das sehe muss ich : $SPDO = SPDO::getInstance();
immer wieder in die Methode mit einbauen.
In welche Methode?

Zitat:
Damit eine Verbindung möglich ist.
Gibt es keine Lösung dazu einmal die $SPDO = SPDO::getInstance();
anzuwenden, damit Sie überall anwendbar ist?
Es gibt natürlich globale Variablen, aber die haben einige schwächen und ich würde davon abraten. Und selbst mit diesem Weg müsstest du in jeder Methode, in der du das Objekt brauchst, dir dieses via „global $SPDO;“ explizit „ranholen“ – hat also nicht wirklich einen Vorteil – aber eben den Nachteil, dass diese Variable anfällig ist.

Ein Singleton ist natürlich in etwa das gleiche in grün, da du ja von überall an das Objekt rankommst, was ja so anscheinend auch gewünscht ist.

Geschickter ist aber es vielleicht, wenn du eine Struktur hast, in der nur die Objekte deine Datenbankverbindung kennen, die sie auch brauchen bzw. benutzen sollen. Wenn diese Objekte alle in eine Kategorie fallen (z.B. dass es alles DAOs sind oder DataObjects), dann kannst du sie vielleicht alle mit einer Fabrik bauen und die Verbindung damit einpflanzen. Damit wäre die DB-Verbindung dann z.B. in allen diesen Objekten via $this->Database verfügbar.

PHP-Code:
<?php

class DaoFactory
{
    protected 
$Database;

    public function 
__construct(SPDO $Database)
    {
        
$this->Database $Database;
    }

    public function 
create($sName)
    {
        return new 
$sName($this->Database);
    }
}

class 
DataObjectFactory
{
    protected 
$DaoFactory;

    public function 
__construct(DaoFactory $DaoFactory)
    {
        
$this->DaoFactory $DaoFactory;
    }

    public function 
create($sName)
    {
        
$Dao $this->DaoFactory->create($sName);
        
        return new 
$sName($Dao);
    }
}

class 
User extends DataObject
{}

abstract class 
DataObject
{
    public function 
save()
    {
        
$this->Dao->update($this->iId$this->aData);
    }
}

class 
Dao_User extends Dao
{
    public function 
update($iId$aData)
    {
        
$this->query("

UPDATE
    `user`

SET
    `email` = '$aData[email]'

WHERE
    `id` = '$iId'

        "
);
    }
}
…ist natürlich sehr starr so, aber eine feine Sache, da du letztlich von der DB-Verbindung nichts mehr mitbekommst, ein Basis-DAO anlegen kannst, das die grundlegenden CRUD-Funktionen selbst macht und ggf. überschrieben werden kann und die DataObjects dann letztlich nurnoch Definitionen über die Attribute und Relationen enthalten müssen, sowie eben Routinen zum Validieren, falls das nicht via Definitionen umsetzbar ist.

Basti
Basti ist offline  
Diesen Beitrag zu to del.icio.us hinzufügen!Diesen Beitrag zu Technorati hinzufügen!Diesen Beitrag zu Mister Wong hinzufügen!
Mit Zitat antworten
Alt 02.03.2008, 13:07 Nach oben    #7
Neuer Benutzer
 
Registriert seit: 17.09.2006
Beiträge: 6
Standard

Ich meinte halt so :
Und normal sollte in der Datei index.php,
die PDO Klasse einmal aufgerufen werden, somit dass Sie in den Klassen verfügbar ist.

Damit ich nicht immer global verwenden muss.
Ich merke dass ich noch einiges nachholen muss über php5
Aber danke für deine Hilfe
PHP-Code:
<?php
class User
{
    public function 
userdata()
    {
        
$SPDO SPDO::getInstance();
        
        
$dbuser $SPDO->prepare("Hier Abfrage");
        
usw.
    }
}
Beckham ist offline  
Diesen Beitrag zu to del.icio.us hinzufügen!Diesen Beitrag zu Technorati hinzufügen!Diesen Beitrag zu Mister Wong hinzufügen!
Mit Zitat antworten
Alt 02.03.2008, 14:48 Nach oben    #8
Bastian Fenske
 
Registriert seit: 04.01.2006
Ort: Kassel
Beiträge: 867
Standard

In dem Fall macht es sicher Sinn, das PDO-Objekt im Konstruktor als Objekt-Eigenschaft zu speichern:
PHP-Code:
class User
{
    protected 
$SPDO;

    public function 
__construct()
    {
        
$this->SPDO SPDO::getInstance();
    }

    public function 
something()
    {
        
$this->SPDO->doSomething();
    }


Basti
Basti ist offline  
Diesen Beitrag zu to del.icio.us hinzufügen!Diesen Beitrag zu Technorati hinzufügen!Diesen Beitrag zu Mister Wong hinzufügen!
Mit Zitat antworten
Antwort

Lesezeichen


Aktive Benutzer in diesem Thema: 1 (Registrierte Benutzer: 0, Gäste: 1)
 
Themen-Optionen Thema durchsuchen
Thema durchsuchen:

Erweiterte Suche

Forumregeln
Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks sind an
PingBacks sind an
RefBacks sind aus

Ähnliche Themen
Thema Autor Forum Antworten Letzter Beitrag
PDO vs MDB2 ex³ PEAR, PECL und Frameworks 1 30.07.2007 12:47
Frage zu PDO Fetch Class ex³ PHP-Programmierung 4 17.02.2007 17:46
Probleme mit Strato / Arcor? MrNiceGuy Plauderecke 15 28.12.2006 23:35
Caching mittels dbm-Dateien, Probleme mit dba_popen() Ben PHP-Programmierung 4 27.07.2006 13:23


Alle Zeitangaben in WEZ +1. Es ist jetzt 16:27 Uhr.


Powered by vBulletin® Version 3.7.4 (Deutsch)
Copyright ©2000 - 2009, Jelsoft Enterprises Ltd.
Search Engine Optimization by vBSEO 3.2.0

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45