Noções básicas sobre OOP - como usar a conexão PDO em outras classes

Acho que tenho um problema em entender como o OOP funciona. Eu já mudei o código que funciona, mas não é a maneira mais adequada que penso. Seguinte cenário (Não, não estou criando um login de usuário sozinho, é realmente apenas para o desenvolvedor local entender melhor o POO):

Eu tenho um arquivo database.php:

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;
    }
}

Então, nesta classe, estou criando uma conexão com o banco de dados e retorno a conexão (objeto?)

Então eu tenho uma segunda classe, a famosa classe User (na verdade eu não estou usando carregamento automático, mas eu sei sobre isso):

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;
        }
    }
}

Então, essas são minhas duas aulas. Nada grande, como você vê. Agora, não fique confuso sobre o nome da funçãologin - Na verdade, apenas tento selecionar alguns nomes de usuário e e-mails do banco de dados e exibi-los. Eu tento conseguir isso:

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

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

E aí vem o problema. Quando executo esse código, recebo a seguinte mensagem de erro:

Erro não capturado: Chame o método indefinido Database :: prepare ()

E não tenho certeza se realmente entendi o que causa esse erro.

O código funciona bem quando altero o seguinte:

mudança$conn no database.php para public em vez de private (acho ruim ...? Mas quando privado, só posso executar consultas dentro da classe Database, estou certo? Então, devo colocar todas essas consultas na classe Database ? Eu acho que é ruim, porque em um grande projeto ele se tornará realmente grande ..)

E a segunda alteração que devo fazer é: Alterar$this->conn->prepare para$this->conn->conn->prepare no arquivo user.php. E aqui eu realmente não tenho idéia do porquê.

Quero dizer, no construtor do user.php eu tenho um$this->conn = new Database() e como o novo banco de dados retornará o objeto de conexão da classe DB, eu realmente não sei por que deve haver um segundoconn->

Eu ficaria muito agradecido se alguém pudesse me explicar um pouco melhor. Conheço a visibilidade das variáveis e li muito sobre isso, mas acho que não entendi no momento, caso contrário não teria esse problema.

Obrigado por todos os conselhos! :)

questionAnswers(1)

yourAnswerToTheQuestion