【问题标题】:Avoid calling Database class in every function避免在每个函数中调用数据库类
【发布时间】:2017-05-10 18:51:27
【问题描述】:

我正在尝试学习 OOP php,并且在开发登录/注册系统时,我注意到我在用户类的每个函数中都调用了数据库类。

例如,像这样:

<?php

class Users {
    public function signUp($username, $email, $password){
        $db = new Database;
        $dbh = $db->connect();

        $sql = "INSERT INTO users (username, email, password) VALUES (?, ?, ?)";

        try {
            $query = $dbh->prepare($sql);
            $query->execute(array($username, $email, $password));

            echo 'succ';
        } catch (Exception $ex) {
            echo $ex->getMessage();
        }
    }

基本上,在不复制整个文件的情况下,我有一些函数可以与数据库一起使用,并且在每个函数中我都必须调用这两行:

$db = new Database;
$dbh = $db->connect();

所以我在互联网上查找了有关 spl_autoload_register 的信息。它在大多数情况下工作得很好,但是我似乎无法像这样替换上面的两行:

$db = new Database;
$dbh = Database::connect();

当我从我的数据库类中得到另一个错误时:

在 D:\xampp\htdocs\PHP 中不在对象上下文中时使用 $this OOP\customSystem\Classes\Class.Database.php 第 24 行

第24行是这个函数的返回

public function connect(){
        return $this->conn; 
    }

我现在不知道该做什么,但它也不能解决我最初在每个函数中调用 Database 类的问题。那么,我需要做什么?

【问题讨论】:

  • Class.Database.php的邮政编码
  • 利用构造函数
  • Database::connect() 表示类静态方法。您的 IDE 应该警告您混合实例和静态上下文。 $db-&gt;connect() 可以与您的代码一起使用,因为 $db 是数据库的一个实例。
  • 是的,$db->connect() 有效,但我想使用 spl_autoload_register 函数并避免在每个函数中调用 Database 类。或者如果我这样做可以吗?

标签: php mysql oop


【解决方案1】:

您应该将 DB 类作为依赖项传入。

它应该看起来像这样

class Users {
    private $dbh;

    public function __construct(\PDO $dbh) 
    {
        $this->dbh = $dbh;
    }     

    public function signUp($username, $email, $password)
    {
        $sql = "INSERT INTO users (username, email, password) VALUES (?, ?, ?)";

        try {
            $query = $this->dbh->prepare($sql);
            $query->execute(array($username, $email, $password));

            echo 'succ';
        } catch (Exception $ex) {
            echo $ex->getMessage();
        }
    }
}

这种方法允许您将 same PDO 实例传递给所有需要它的类。您还可以通过使用工厂来进一步改进代码,该工厂负责创建所有需要 PDO 作为依赖项的类,如 this answer 中所述。

【讨论】:

  • 抱歉这么晚才回复,非常感谢,这正是我需要的!
【解决方案2】:

当您静态调用方法 Database::connect(); 时,您不能引用 $this
$this 是对其中对象的现有实例的引用。 因此,当您通过 new Database() 创建新实例时,您可以在 Database 类方法中使用 $this 指针。

只需了解有关静态事物的更多信息并尝试以下操作:

class Database
{
    private static $instance = null;
    private static $conn = null;

    private function __construct()
    {
        try {
            $dbh = new PDO(DB_SOCKET_TYPE . ':host=' . DB_HOST . ';dbname=' . DB_NAME . ';charset=utf8', DB_USER, DB_PASSWORD);
            $dbh->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
            self::$conn = $dbh;
        } catch (PDOException $e) {
            echo $e->getMessage();
        }
    }

    private function getDbConnection()
    {
        return self::$conn;
    }

    public static function connect()
    {
        if (self::$instance === null) {
            self::$instance = new self();
        }

        return self::$instance->getDbConnection();
    }
}

// how to use it? for eg.
$sql = 'INSERT INTO users (username, email, password) VALUES (?, ?, ?)';
$query = Database::connect()->prepare($sql);
$query->execute(array($username, $email, $password));

抱歉有任何错误,但我写得很快,没有测试它
希望有用

【讨论】:

  • 我收到一个错误:致命错误:在第 178 行的 D:\xampp\htdocs\PHP OOP\customSystem\Classes\Class.Users.php 中调用一个成员函数 prepare() on null是 $query = Database::connect()->prepare($sql);行
  • 好吧,经过几个小时的努力,我通过添加新数据库让它工作;在拥有 Database::connect()->prepare($sql);不,字符串,什么都没有。它应该是这样工作的吗?
  • @user3628807 抱歉,我的代码出错了。现在它应该可以正常工作了。看看这个
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-03-30
  • 2021-04-02
  • 1970-01-01
  • 2012-11-19
  • 2021-11-10
相关资源
最近更新 更多