Wie verwende ich die PDO-Verbindung in anderen Klassen?

Lesezeit: 5 Minuten

Wie verwende ich die PDO Verbindung in anderen Klassen
Zwillingsfreunde

Ich glaube, ich habe ein Problem damit, zu verstehen, wie OOP funktioniert. Ich habe bereits den Code geändert, dass es funktioniert, aber es ist nicht der richtige Weg, denke ich. Folgendes Szenario (Nein, ich erstelle kein Benutzerlogin selbst, es ist wirklich nur für lokale Entwickler, um OOP besser zu verstehen):

Ich habe eine database.php-Datei:

class Database {

    /* Properties */
    private $conn;
    private $dsn = 'mysql:dbname=test;host=127.0.0.1';
    private $user="root";
    private $password = '';

    /* Creates database connection */
    public function __construct() {
        try {
            $this->conn = new PDO($this->dsn, $this->user, $this->password);
        } catch (PDOException $e) {
            print "Error!: " . $e->getMessage() . "";
            die();
        }
        return $this->conn;
    }
}

In dieser Klasse erstelle ich also eine Datenbankverbindung und gebe die Verbindung (Objekt?)

Dann habe ich eine zweite Klasse, die berühmte User-Klasse (eigentlich verwende ich kein Autoload, aber ich weiß davon):

include "database.php";

class User {
    /* Properties */
    private $conn;

    /* Get database access */
    public function __construct() {
        $this->conn = new Database();
    }

    /* Login a user */
    public function login() {
        $stmt = $this->conn->prepare("SELECT username, usermail FROM user");
        if($stmt->execute()) {
            while($rows = $stmt->fetch()) {
                $fetch[] = $rows;
            }
            return $fetch;
        }
        else {
            return false;
        }
    }
}

Das sind also meine zwei Klassen. Nichts Großes, wie Sie sehen. Lassen Sie sich jetzt nicht durch den Funktionsnamen verwirren login – Eigentlich versuche ich nur, einige Benutzernamen und Benutzermails aus der Datenbank auszuwählen und sie anzuzeigen. Dies versuche ich zu erreichen durch:

$user = new User();
$list = $user->login();

foreach($list as $test) {
    echo $test["username"];
}

Und hier kommt das Problem. Wenn ich diesen Code ausführe, bekomme ich folgende Fehlermeldung:

Nicht erfasster Fehler: Aufruf der undefinierten Methode Database::prepare()

Und ich bin mir nicht sicher, ob ich wirklich verstehe, was diesen Fehler verursacht.

Der Code funktioniert gut, wenn ich die folgenden Dinge ändere:

Ändern $conn in database.php auf öffentlich statt privat (ich denke, das ist schlecht …? Aber wenn es privat ist, kann ich nur Abfragen innerhalb der Database-Klasse ausführen, habe ich Recht? Soll ich also alle diese Abfragen in die Database-Klasse stellen? ? Das finde ich schlecht, denn bei einem großen Projekt wird es schon richtig groß..)

Und die zweite Veränderung, die ich machen muss, ist: Veränderung $this->conn->prepare zu $this->conn->conn->prepare in der user.php-Datei. Und hier habe ich wirklich keine Ahnung warum.

Ich meine, im Konstruktor der user.php Ich habe eine $this->conn = new Database() und da mir die neue Datenbank das Verbindungsobjekt aus der DB-Klasse zurückgibt, weiß ich wirklich nicht, warum es eine zweite geben muss conn->

  • Der Konstruktor sollte nichts zurückgeben: stackoverflow.com/questions/6849572/… – um Zugriff auf diese Methode zu haben Database Klasse müsste verlängert werden PDO

    – CD001

    26. April 2017 um 9:58 Uhr

  • Dein Fehler ist $this->conn->prepare( Sie versuchen, die Vorbereitungsfunktion für Ihre Datenbankklasse aufzurufen, aber es gibt keine Vorbereitungsfunktion. du könntest das machen $conn of Database public, was dazu führen würde $this->conn->conn->prepare. der Rückgabewert Ihrer Datenbank __construct() gibt ein Datenbankobjekt zurück, nicht die Verbindung, selbst wenn Sie retrun $this->conn

    – Nitro.de

    26. April 2017 um 9:59 Uhr


  • das ist richtig, denn in Ihrem Database Klasse conn ist PDO Beispiel und hat solche Fähigkeiten

    – xmike

    26. April 2017 um 10:01 Uhr

  • @Twinfriends ja, da bin ich mir sicher. Wenn Sie das Login in die Datenbankklasse einfügen, $this->conn ist das PDO-Objekt von Database, nicht das Database-Objekt selbst

    – Nitro.de

    26. April 2017 um 10:02 Uhr


  • Innerhalb der Datenbankklasse, die Sie aufrufen würden $this->conn – in diesem Fall das ist eine PDO-Instanz, also existiert die Methode und gut ist. Wenn Sie instanziieren Database aber von außen erschaffst du ein neues Database Objekt, das nur die von Ihnen definierten Methoden hat – es sei denn, Sie erweitern eine andere Klasse.

    – CD001

    26. April 2017 um 10:02 Uhr

Wie verwende ich die PDO Verbindung in anderen Klassen
Ihr gesunder Menschenverstand

  • Ihre aktuelle Klasse ist ziemlich nutzlos. Es wäre sinnvoll, einen Datenbank-Wrapper zu erstellen, wenn er PDO einige zusätzliche Funktionen hinzufügt. Aber angesichts des aktuellen Codes ist es besser, stattdessen Vanilla PDO zu verwenden.
  • Erstellen Sie in jedem Fall eine Einzel $db-Instanz entweder von Vanilla PDO oder Ihrer Datenbankklasse.
  • Übergeben Sie es als Konstruktorparameter in jede Klasse, die eine Datenbankverbindung benötigt

Datenbank.php:

<?php
$host="127.0.0.1";
$db   = 'test';
$user="root";
$pass="";
$charset="utf8";

$dsn = "mysql:host=$host;dbname=$db;charset=$charset";
$opt = [
    \PDO::ATTR_ERRMODE            => \PDO::ERRMODE_EXCEPTION,
    \PDO::ATTR_DEFAULT_FETCH_MODE => \PDO::FETCH_ASSOC,
    \PDO::ATTR_EMULATE_PREPARES   => false,
];
$pdo = new \PDO($dsn, $user, $pass, $opt);

user.php

<?php
class User {
    /* Properties */
    private $conn;

    /* Get database access */
    public function __construct(\PDO $pdo) {
        $this->conn = $pdo;
    }

    /* List all users */
    public function getUsers() {
        return $this->conn->query("SELECT username, usermail FROM user")->fetchAll();
    }
}

app.php

include 'database.php';
$user = new User($pdo);
$list = $user->getUsers();

foreach($list as $test) {
    echo $test["username"],"\n";
}

Ausgang:

username_foo
username_bar
username_baz

Sieh dir mein an (Das einzig richtige) PDO-Tutorial für weitere PDO-Details.

  • Dies ist zwar eine nette Art, es zu lösen, aber ich persönlich mag die Verbindung nicht in meinen Modellen. Um es “sauber” zu halten, könnte man auch ein Basismodell erweitern, das die Verbindungsmethoden enthält.

    – Niek van der Maaden

    26. April 2017 um 10:20 Uhr

  • @NiekvanderMaaden Wenn Sie ein Basismodell erweitern, haben Sie die Verbindung auch in der Nachkommenklasse.

    – Ihr gesunder Menschenverstand

    26. April 2017 um 10:23 Uhr

  • Das ist richtig, aber was ich meinte, ist, dass Ihr untergeordnetes Modell im Sinne der Lesbarkeit “sauber” ist, dass es nicht mit zusätzlichen Methoden und Variablen verstopft wird. Auf die eine oder andere Weise besteht die einzig wahre Möglichkeit, sie nicht in Ihrem Modell zu haben, darin, eine statische Datenbankklasse zu verwenden, aber ja, das ist nicht der richtige Weg, dies zu tun.

    – Niek van der Maaden

    26. April 2017 um 10:24 Uhr


  • @NiekvanderMaaden Wenn Sie möchten, dass Ihre Klassen sauber sind, suchen Sie nach dem Data Mapper-Muster.

    – Ihr gesunder Menschenverstand

    26. April 2017 um 10:25 Uhr

  • Wenn ich 3 Objekte habe, die dieselbe DB-Verbindung in derselben Iteration teilen, ist das eine schlechte Sache?

    – Botea Florin

    23. November 2018 um 16:16 Uhr

985780cookie-checkWie verwende ich die PDO-Verbindung in anderen Klassen?

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy