搜索

首页  >  问答  >  正文

在其他类中使用PDO连接的方法

<p>我觉得我在理解面向对象编程(OOP)的工作原理方面有问题。我已经改变了代码,使其能够工作,但我认为这不是正确的方式。以下是一个场景(不,我不是自己创建用户登录,这只是为了更好地理解OOP):</p> <p>我有一个database.php文件:</p> <pre class="brush:php;toolbar:false;">class Database { /* 属性 */ private $conn; private $dsn = 'mysql:dbname=test;host=127.0.0.1'; private $user = 'root'; private $password = ''; /* 创建数据库连接 */ 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; } }</pre> <p>所以在这个类中,我创建了一个数据库连接,并返回连接(对象?)</p> <p>然后我有一个第二个类,著名的User类(实际上我没有使用自动加载,但我知道它):</p> <pre class="brush:php;toolbar:false;">include "database.php"; class User { /* 属性 */ private $conn; /* 获取数据库访问 */ public function __construct() { $this->conn = new Database(); } /* 登录用户 */ 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; } } }</pre> <p>这就是我的两个类。如你所见,没有什么大不了的。现在,请不要对函数名<code>login</code>感到困惑 - 实际上,我只是尝试从数据库中选择一些用户名和用户邮件,并将它们显示出来。我尝试通过以下方式实现:</p> <pre class="brush:php;toolbar:false;">$user = new User(); $list = $user->login(); foreach($list as $test) { echo $test["username"]; }</pre> <p>这里出现了问题。当我执行这段代码时,我得到以下错误消息:</p> <blockquote> <p>未捕获的错误:调用未定义的方法Database::prepare()</p> </blockquote> <p>我不确定我真的理解这个错误的原因。</p> <p><strong>当我改变以下内容时,代码可以正常工作:</strong></p> <p>将database.php中的<code>$conn</code>从private改为public(我认为这是不好的...?但当它是private时,我只能在Database类内部执行查询,对吗?那么我应该将所有这些查询放在Database类中吗?我认为这是不好的,因为在一个大项目中,它将变得非常庞大...)</p> <p>第二个改变是:</p> <p>将user.php文件中的<code>$this->conn->prepare</code>改为<code>$this->conn->conn->prepare</code>。对此我真的没有想法。</p> <p>我的意思是,在<code>user.php</code>的构造函数中,我有一个<code>$this->conn = new Database()</code>,由于new Database将返回来自DB类的连接对象,我真的不知道为什么这里必须有第二个<code>conn-></code></p>
P粉293550575P粉293550575462 天前483

全部回复(1)我来回复

  • P粉451614834

    P粉4516148342023-08-25 11:13:39

    • 不要创建像Database这样的类,因为它没有什么用。如果它能为PDO添加一些额外的功能,那么创建一个数据库封装类是有意义的。但是考虑到它当前的代码,最好使用原始的PDO。
    • 从原始的PDO或者你的数据库类中创建一个单一的 $db 实例。
    • 将它作为构造函数参数传递给每个需要数据库连接的类。

    database.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";
    }

    output:

    username_foo
    username_bar
    username_baz

    查看我的(唯一正确的)PDO教程以获取更多PDO的详细信息。

    回复
    0
  • 取消回复