Eigene PDO-Class

Sasser

Erfahrenes Mitglied
Hallo zusammen :)

Ich habe mir eine eigene PDO-Klasse gebaut und bekomme es aber mit den Instanzen nicht so recht hin.

Ich erhalte die Fehlermeldung, dass die Tokens nicht mit den Variablen übereinstimmen. Es liegt daran, dass sich die beiden Abfragen vermischen. Kann mir jemand helfen, sodass der Fehler nicht mehr auftritt?

PHP:
class Database {

    private $statement;
    private $connection;
    private $error;

    function __construct() {
        $this->config = include( dirname(__FILE__) . "/config.php" );
        $this->connect();
    }

    public function quote( $param ) {
        return $this->connection->quote( $param );
    }

    public function query( $query ) {
        $this->statement = $this->connection->prepare( implode( " ", $query ) );
        return $this;
    }

    public function param( $param, $value ) {
        switch( true ) {
            case is_int( $value ): {
                $this->statement->bindValue( $param, $value, PDO::PARAM_INT );
                break;
            }
            case is_bool( $value ): {
                $this->statement->bindValue( $param, $value, PDO::PARAM_BOOL );
                break;
            }
            case is_null( $value ): {
                $this->statement->bindValue( $param, $value, PDO::PARAM_NULL );
                break;
            }
            default: {
                $this->statement->bindValue( $param, $value, PDO::PARAM_STR );
            }
        }
    }

    public function execute( $params = array() ) {
        if (count( $params ) > 0) {
            return $this->statement->execute( $params );
        } else {
            return $this->statement->execute();
        }
    }

    public function value() {
        $this->execute();
        return $this->statement->fetchColumn();
    }

    public function result() {
        $this->execute();
        return $this->statement->fetch( PDO::FETCH_ASSOC );
    }

    public function results() {
        $this->execute();
        return $this->statement->fetchAll( PDO::FETCH_ASSOC );
    }

    public function count() {
        $this->execute();
        return $this->statement->rowCount();
    }

    private function connect() {
        try {
            $config = "mysql:host=" . $this->config ["DBhost"] . ";dbname=" . $this->config ["DBname"] . ";charset=UTF8MB4";
            $this->connection = new PDO( $config, $this->config ["DBuser"], $this->config ["DBpass"] );
        } catch( PDOException $error ) {
            $this->error = $error->getMessage();
        }
    }

}

PHP:
class Test {

    function __construct() {
        $this->DB = new Database();
    }

    public function test() {
        $query [0] = "SELECT * FROM user WHERE user = :user";
        $test = $this->DB->query( $query );
        $test->param( ":user", $this->getUser() );
        return $test->results();
    }

    private function getUser() {
        $query [0] = "SELECT user FROM user WHERE username = :username";
        $test = $this->DB->query( $query );
        $test->param( ":username", "admin" );
        return $test->value();
    }

}

$test = new Test();
var_export( $test->test() );
 
PHP:
implode( " ", $query )
Bei dir ist aber $query ein String, kein Array

Anosnten. Gib mal die ganze Fehlermeldung.
 
Das habe ich nur als Beispiel drin, lasse ich die getUser()-Methode weg, dann funktioniert es wieder. Ich denke es liegt daran, dass ich die Instanzen miteinander vermische oder so.

Die Fehlermeldung lautet:

Warning: PDOStatement::execute(): SQLSTATE[HY093]: Invalid parameter number: number of bound variables does not match number of tokens in /class/database.class.php on line 46
 
Jepp. Grenau das ist es. Du hast nur eine Instanz der Datenbankklasse.
mit dem ersten Test setzt du $this->Statement auf "SELECT * FROM user WHERE user = :user".
Bevor das SQL ausgeführt wird, überschreibst du du das Statement auf "SELECT user FROM user WHERE username = :username"
Nachher ist das erste SQL natürlich verloren.

Entweder getrennt Instanzen
PHP:
 private function getUser() {
  $db = new Database();
     $query [0] = "SELECT user FROM user WHERE username = :username";
     $db->query( $query );
     $db->param( ":username", "admin" );
     return $db->value();
 }

oder die Reiehnfolge anpassen
PHP:
 public function test() {
  $user = $this->getUser();
     $query [0] = "SELECT * FROM user WHERE user = :user";
     $this->DB->query( $query );
     $this->DB->param( ":user", $user );
     return $this->DB->results();
 }

Ich persönlich würde für getUser() eine eigene Instanz zur Verfügung stellen.

Achja, dein Rückgabewert bei query() ist nur eine Refernez auf die bestehende Instanz von Database
 
Vielen Dank für deine Antwort!

Bei der ersten Variante würde es aber doch auch bedeuten, dass ich jedes Mal eine neue DB-Verbindung aufbaue?

Ich würde es gerne so ähnlich nutzen wie die Urform der PDO-Klasse:

$statement = $pdo->prepare("SELECT * FROM users");
$statement->execute(array('Max', 'Mustermann'));

Ich möchte quasi die Instanz außerhalb speichern, aber daran scheitere ich irgendwie.
 
Zuletzt bearbeitet:
Bzw. ist es möglich, die PDO-Klasse einfach zu erweitern bzw. für meine Zwecke zu vereinfachen?
 
Danke dir, ich werde weiter probieren bis ich meine Klasse zum Laufen bringe oder ich muss aufpassen dass ich nur eine Abfrage immer mache.
 
Zurück