• Jetzt anmelden. Es dauert nur 2 Minuten und ist kostenlos!

Nochmal Objekte

achtelpetit

Neues Mitglied
Bezug: http://www.html.de/php/39813-gehoert-eine-klasse.html
Diesen Thread hatte ich dieser Tage eröffnet, jetzt habe ich schon wieder (oder immer noch) Verständnisschwierigkeiten.
PHP:
class DB {
    public function __construct($dbname) 
    {
        $user ='root';
        $pw = '';
        $db = new PDO('mysql:host=localhost;dbname=' . $dbname, $user, $pw);
        var_dump($db); //  wie erwartet: object(PDO)#3 (0) { }
        return $db;
    }
};    


class Visitor {
    function is_registered($check_nickname, $check_pwhash) 
    {
        $db = new DB('shop');
        var_dump($db);   // jetzt kein PDO mehr: object(DB)#2 (0) { } 
        // hier kommt noch allerlei
    }
};
Die Konstruktion, die ich oben zeige, soll mir eigentlich einen Datenbankzugriff ermöglichen. Die Sache funktioniert aber nur, wenn ich das PDO-Objekt direkt in der class Visitor erzeuge. Wenn ich in "Visitor" ein Objekt "DB" erzeuge, ist das kein PDO-Objekt mehr. Ich vermute, daß das DB-Objekt irgendwie das PDO-Objekt enthält, aber ich komme nicht dran.
Vielleicht hat jemand die Geduld, mich aufzuklären.
 
Werbung:
Der Konstruktor kann keinen Wert zurückgeben. $db enthält somit ein Objekt der Klasse „DB“.

Es ist auch sinnfrei, denn so könnte man direkt auf dem PDO-Objekt arbeiten.
 
Es sollte so gehen:
PHP:
class DB
{
   private $db;
   public function __construct($dbname)
   {
      $this->db = new PDO ....
      ....
    }
  public function getDB
  {
    return $this->db;
  }
}

class Visitor
{
  public function is_registered(....)
  {
     $DBobj = new DB('shop'); // DB-Objekt
     $db = $DBobj->getDB(); // PDO-Objekt
   }
}
 
Werbung:
Lieber so:
PHP:
class My_Db_Adapter_Pdo_Mysql
{
    protected $_connection = null;
    protected $_database = null;
    protected $_host = null;
    protected $_port = null;
    protected $_username = null;
    protected $_password = null;
    protected $_charset = null;

    /**
     *
     * @param string  $host
     * @param integer $port
     * @param string  $database
     * @param string  $username (optional)
     * @param string  $password (optional)
     */
    public function __construct(array $options)
    {
        if (array_key_exists('database', $options)) {
            $this->_database = $options['database'];
        }
        // usw.
    }

    public function getConnection()
    {
         if (null === $this->_connection) {
            $this->_connection = new PDO(
                sprintf('mysql:host=%s;port=%d;dbname=%s', $this->_host, $this->_port, $this->_database),
                $this->_username,
                $this->_password
            );
        }
    }

    /**
     * @param string $query
     */
    public function query($query)
    {
        $connection = $this->getConnection();
        $result = $connection->query($query);
        // result in ein neues Objekt verpacken z.B. My_Db_Rowset, welches
        // My_Db_Row-Objekte hält welche die Daten enthalten
    }
}

class My_Db
{
    static protected $_adapters = array();
    static protected $_defaultAdapter = null;

    static public function adapterFactory($type, $options)
    {
        $adapterClass = 'My_Db_Adapter_' . ucfirst($type);
        $adapter = new $adapterClass($options);
        
        if (null == $this->_defaultAdapter) {
            $this->_defaultAdapter = $adapter;
        }
   
        self::_adapters[] = $adapter;
        return $adapter;
    }

    public function getAdapter($name = null)
    {
        if (null === $name) {
            return self::_defaultAdapter;
        }

        // Möglichkeit den Adapter nach einem Namen zu erhalten
    }

    public function query($query)
    {
        $this->getAdapter()->query($query);
    }
}

class My_Model_Foobar
{
    protected $_adapter = null;

    public function setAdapter(/*My_Db_Adapter_Abstract*/ $adapter)
    {
        $this->_adapter = $adapter;
        return $this;
    }

    public function getAdapter()
    {
        return $this->_adapter;
    }

    public function fetchAll()
    {
        return $this->getAdapter()->query(
            'SELECT * FROM foobar'
        );
    }
}

// My_db liefert gleichzeitig ein Interface mit der Datenbank direkt zu arbeiten
$adapter = new My_Db::adapterFactory('Pdo_Mysql', array(... options ...));

$model = new My_Model_Foobar();
$rows = $model->setAdapter($adapter)
          ->fetchAll();

Mächtig wird das ganze erst wenn man auch noch die Tabellen in Klassen ablegt, die Models über einen Mapper aufruft und für die Abfragen ebenfalls Objekte durchreichen kann (das alles liefert Zend_Db).
 
Herzlichen Dank für Eure Antworten.
@Kratzbaum
Wie Du es beschrieben hast funktioniert es, merci. Ich wußte nicht, daß ein Konstruktor keine Rückgabe hat. Mir ist auch unverständlich, warum das so ist, komme ich aber noch hinter.
@crash
Dein Beispiel kann ich leider nicht verstehen, das übersteigt meine Kenntnisse. Ich heb's mir auf und schaue es in ein paar Wochen nochmal an.
 
Vorteil von meiner Implementation ist eben, dass die Adapter gekapselt sind. D.h. es kann auch Mysqli, PDO_Sqlite oder MeineXmlDatenbank implementiert werden und über das einheitliche Interface genutzt werden. Genau das macht OOP ja aus.
 
Werbung:
Einen Sch*** macht genau das OOP aus ^^
OOP ist nicht dafür da um alles möglichst abstrakt gestalten zu können.
In einer umgebung in der du etwas entwickelst musst du in den meisten Fällen nicht darauf achten das die Datenbank ausgetauscht werden kann oder sonstiges. Du entscheidest dich vielmehr für eine die DEINEN ANFORDERUNGEN entspricht.
Dazu schreibst du dann schönen Code der, um einige Programmierer zu schonen, gerne OO sein kann und gut ist.

Soviel nur um diese geöffnete Frage die aufkommen SOLLTE zu schließen ^^
@crash du musst diesen Post ignorieren damit das hier kein flamewar wird... wenn du meckern willst schreib mich lieber an :)

lg
 
Die Anforderungen an einer Webapplikationen können sich mit der Zeit ändern. Das kann Kosten- oder Effizienzgründe haben. Mit meinen Anforderungen hat das rein gar nicht zu tun.

Und dass das im konkreten Fall bei Datenbanken der Fall sein kann zeigt der Bedarf an solchen Abstraktionsschichten: Zend_Db, Doctrine, Propel und die anderen unzähligen ORMs. Es ist also eine zukunftssichere und mit geringen Problemen verbundene Entscheidung gleich mit so ein Tool zu arbeiten, bzw. im allgemeinen Fall ausreichend zu abstrahieren. Natürlich immer im Rahmen der Zeit und mit dem Bewusstsein, dass kein System perfekt ist.

Und doch: für Abstrahierung ist OOP gedacht, sonst würde man so etwas wie Vererbung und Kapselung gar nicht benötigen.
 
Zurück
Oben