PHP Singleton数据库查询

时间:2012-03-27 20:34:58

标签: php database singleton

在PHP中,我有以下单例数据库类:

class Database
{
    private static $instance;

    private function __construct()
    {
        self::$instance = new mysqli('localhost', 'root', 'Matthias', 'financecontrol', '3307');
        if (!self::$instance) {
            throw new Exception('Could not connect to database in function __construct.');
        }
    }

    public static function getInstance()
    {
        if (!self::$instance) {
            self::$instance = new Database();
        }
        return self::$instance;
    }

}

每当我尝试在另一个PHP文件中对数据库执行查询时,例如检查用户是否已经存在:

function userExists($username)
    {
        try {
            $connection = Database::getInstance();

            $result = $connection->query("select * from user where username='$username'");
            if (!$result) {
                throw new Exception("Connection to database failed in function userExists.");
            }
            if ($result->num_rows > 0) {
                return true;
            } else {
                return false;
            }
        } catch (Exception $ex) {
            $errorPager = new ErrorpageGenerator();
            $errorPager->generateErrorPage($ex->getMessage());
            return false;
        }
    }

我收到错误消息“PHP致命错误:在第44行的User.php中调用未定义的方法Database :: query()”

我已经尝试在Database类中添加查询功能,但似乎没有解决问题。有任何想法吗?感谢

3 个答案:

答案 0 :(得分:2)

当然,您必须添加此方法。但是你不能将Database()和mySQLi对象分配给m_pInstance

所以:

class Database
{
  private static $conn;

  // ...
  public function __construct() 
  {
     self::$conn = new mysqli('localhost', 'root', 'root', 'database', '3307');
     //...

然后

public function query($sql)
{
  return self::$conn->query($sql);
  // or 
  return mysqli_query(self::$conn, $sql);
}

修改

工作代码:

class Database
{
  private static $instance = null;

  private static $conn;

  private function __construct()
  {
    self::$conn = new mysqli('localhost', 'root', 'root', 'database', '3307');
  }

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

    return self::$instance;
  }

  public function query($sql)
  {
    return self::$conn->query($sql);
  }
}

答案 1 :(得分:1)

您收到此错误,因为Database::$m_pInstance包含Database类和 MySQLi实例的实例。您在部分代码之间创建了“冲突”:

public static function getInstance()
{
    if (!self::$m_pInstance) {
        self::$m_pInstance = new Database(); // << PROBLEM
    }

    return self::$m_pInstance;
}

覆盖了构造函数的作用:

private function __construct()
{
    self::$m_pInstance = new mysqli( /* .. */ ); // PROBLEM
    if (!self::$m_pInstance) {
        throw new Exception('Could not .. blah');
    }
    else {
        return self::$m_pInstance;
    }
}

即使构造函数为MySQLi对象的实例分配self::$m_pInstance,它也会被self::$instance = new Database();覆盖。

另外,在php __constuct()中,方法不应该return

那就是说,我认为应该警告你单身被认为是反模式,应该避免。您的代码也有意想不到的副作用,迫使每个应用程序只有一个数据库(不是连接,数据库)。

您可能会从看几个讲座中受益:

答案 2 :(得分:0)

您的代码看起来不正确。

首先,为$ m_pInstance分配一个新的数据库实例。但是,在构造函数中,为它分配一个新的mysqli实例。我不确定php如何处理这种情况,但它似乎将它视为数据库对象,如您的错误消息所示。但是,Database类没有查询方法。

因此,解决方案是将mysqli对象保存在不同的字段中,并为其添加getter和setter,或者将方法委托给它。