【问题标题】:Undefined method, using PDO outside the class未定义的方法,在类外使用 PDO
【发布时间】:2017-05-09 12:48:42
【问题描述】:

尝试在连接类之外运行查询时出现以下错误。

致命错误:在...中调用未定义的方法 Core\Database::query()

我有以下文件。

数据库.php

namespace Core;

use \PDO;

class Database
{
    private $pdo;
    private static $instance;

    private function __construct()
    {
        try {
            $this->pdo = new PDO("mysql:host=localhost;dbname=db;", "root", "pw");
            $this->pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
        } catch (\PDOException $e) {
            echo $e->getMessage();
        }
    }

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

Auth.php

namespace Auth;

use Core\Database;

class Auth
{
    protected $dbh;

    public function __construct()
    {
        $this->dbh = Database::getInstance();
        $query = $this->dbh->query("SELECT * FROM table");
    }
}

提前感谢您的帮助。

【问题讨论】:

  • 就像错误所说的那样,您的 Database 类中没有查询方法。 getInstance() 返回 Database 类的实例,而不是 PDO。
  • @Devon,好的:我在 Auth.php 中将 $this->dbh->query 更改为 $this->dbh->pdo->query,但还有其他方法吗?看起来有点乱。
  • 另外,使实例变量$pdo public,否则你将无法在课堂外访问它,尤其是当你调用->query(...)时来自Auth类。
  • 单例数据库对象是一种代码味道。正常构造一个PDO对象,通过Auth对象的构造函数传入。 phptherightway.com/#dependency_injection
  • 您是否通过任何给定的答案解决了问题?如果一个有用的赞成票并且如果它解决了,请标记它。

标签: php class pdo namespaces


【解决方案1】:

您正在设置数据库类的属性并返回一个静态值。也许您可能想这样做:

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

  public function __construct(){
    try {
        parent::__construct("mysql:host=localhost;dbname=db;", "root", "pw", [
          \PDO::ATTR_ERRMODE => \PDO::ERRMODE_EXCEPTION
        ]);

        self::$instance = $this;
    } catch (\PDOException $e) {
        echo $e->getMessage();
    }
  }
}

我个人是这样做的,而不是创建一个愚蠢的包装类。

否则您将不得不设置静态变量:

self::$instance = new PDO("mysql:host=localhost;dbname=db;", "root", "pw");

【讨论】:

    【解决方案2】:

    您在Auth 类中所做的是您刚刚使用Singleton 模式创建了Database 类的实例,并尝试从Database 实例调用query 方法,而这不是在类中定义。如果你想像$this->dbh->query()一样访问它,你需要构造一个Database类的实例,同时返回PDO实例。喜欢这个:

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

    我刚刚在这里修改的是return self::$instance->pdo。如果第一次调用getInstance,则一旦实例化Database 类,这将返回PDO 的对象,否则它只返回创建的PDO 实例。你现在可以在Auth 类中做$this->dbh->query()

    注意,仅当您不打算在 Database 类中定义任何其他方法时才需要这样做,除了 static 方法,如 getInstance。因为getInstance 的结果只允许你访问PDO 属性和方法。因此,解决方案是在Database 中定义一个public 方法,该方法分别返回PDO 实例。

    public static function getInstance() {
        if (!isset(self::$instance))
            self::$instance = new Database();
        return self::$instance;
    }
    
    public function getPDO() {
        return $this->pdo;
    }
    

    完成后,您可以访问 PDO 中的 Auth 类,例如:

    public function __construct()
    {
        $this->dbh = Database::getInstance()->getPDO();
        $query = $this->dbh->query("SELECT * FROM table");
    }
    

    希望对你有帮助!

    【讨论】:

      猜你喜欢
      • 2012-04-01
      • 2012-10-09
      • 2018-04-11
      • 2014-06-15
      • 2012-11-19
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-08-19
      相关资源
      最近更新 更多