【问题标题】:Call to undefined method PHP PDO调用未定义的方法 PHP PDO
【发布时间】:2018-04-11 22:24:47
【问题描述】:

我收到一个错误

调用未定义的方法 Connection::prepare()

错误源于 QueryBuilder 类的 select4 方法(如下)。调用 prepare 方法的第一行。

理想情况下,Connection 类应该将 PDO 对象返回给 QueryBuilder。 好像我将 Connection 对象实例传递给了 QueryBuilder。

私有 $pdo 的 var_dump 的输出

object(QueryBuilder)#4 (1) { 
["pdo":"QueryBuilder":private]=> object(Connection)#2 (0) { } }
object(Connection)#2 (0) { }  

代码说明

我有一个配置类(不包括在内),它接受一个 json 文件(mysql 连接信息)并返回一个数组。

然后传入Connection类返回一个新的PDO对象

class Connection {

  public function __construct($db) {

    $dsn = $db['dbs'] . ':host=' . $db['host'] . ';dbname=' . $db['dbName'];

    return new PDO($dsn, $db['user'], $db['pwd']);

  }
}

QueryBuilder 类接受 PDO 实例并将其存储在私有变量中。

class QueryBuilder {

 private $pdo;

 public function __construct($pdo) {

   $this->pdo = $pdo;

 }

 public function select4($sql) {

   $statement = $this->pdo->prepare(":sql :n");

   $statement->bindValue(n, 4, PDO::PARAM_INT);

   $statement->execute(['sql' => $sql]);

   return $statement->fetch(PDO::FETCH_CLASS);

 }

}

从 Config 类调用 Connection 的新实例传递数组值

$pdo = new Connection(Config::getInstance()->get("db"));

从 Connection 传递 PDO 实例调用 QueryBuilder 的新实例

$query = new QueryBuilder($pdo);

$sql_1 = 'SELECT title, synopsis FROM blog LIMIT';
$blog = $query->select4($sql_1); // triggers error 

更新:

感谢 cmets 和帮助。我更改了 Connection 类以实现公共静态变量 $pdo。我使用构造函数将 PDO 对象分配给静态变量。

class Connection {

  public static $pdo;    // Added a static $pdo

  public function __construct($db) {

    $dsn = $db['dbs'] . ':host=' . $db['host'] . ';dbname=' . $db['dbName'];

    self::$pdo = new PDO($dsn, $db['user'], $db['pwd']);    // assign PDO

  }

}

$pdo = new Connection(Config::getInstance()->get("db"));

$query = new QueryBuilder(Connection::$pdo);

更正了 select4 方法中的一些小错误,现在可以正常使用。 :)

【问题讨论】:

  • 对象不是这样工作的,你不会从构造函数返回任何东西:你的$pdo变量将是Connection的一个实例,而不是PDO。
  • @YourCommonSense :感谢我阅读并实现了通用选择功能。我将仔细检查我的其余代码是否有新手错误:)
  • @jeroen:我还有一个问题:我读过here,execute 方法将所有值绑定为字符串,并且某些子句(如 LIMIT)不接受字符串值。我碰巧从我的代码中删除了 bindValue() 并将所有参数添加到 execute()。没有错误。那么什么时候使用 bindValue()
  • 在您链接到的那段中说过。

标签: php pdo


【解决方案1】:

理想情况下,Connection 类应该将 PDO 对象返回给 QueryBuilder。好像我将 Connection 对象实例传递给了 QueryBuilder。

您无法使用构造函数实现这一点,在构造函数中返回不同的对象不会影响 new 语句返回的内容。见:Constructor returning value?。

您可以尝试以下方法之一:

继承

class Connection extends PDO {

  public function __construct($db) {

    $dsn = $db['dbs'] . ':host=' . $db['host'] . ';dbname=' . $db['dbName'];

    parent::__construct($dsn, $db['user'], $db['pwd']);
  }
}

使用:

// Get Connection object which extends PDO class
$pdo = new Connection(Config::getInstance()->get("db"));

静态方法

class Connection {

  public static function getPDO($db) {

    $dsn = $db['dbs'] . ':host=' . $db['host'] . ';dbname=' . $db['dbName'];

    return new PDO($dsn, $db['user'], $db['pwd']);
  }
}

使用:

// Get PDO object using Connection static method
$pdo = Connection::getPDO(Config::getInstance()->get("db"));

Getter 方法

class Connection {

  /** @var PDO */
  private $pdo;

  public function __construct($db) {

    $dsn = $db['dbs'] . ':host=' . $db['host'] . ';dbname=' . $db['dbName'];

    $this->pdo = new PDO($dsn, $db['user'], $db['pwd']);
  }

  /**
   * Get PDO instance
   * @return PDO
   */
  public function getPDO() {
    return $this->pdo;
  }
}

使用:

// Get PDO object using Connection object
$pdo = (new Connection(Config::getInstance()->get("db")))->getPDO();

你应该看看一些 mysql 包装器,比如 Laravel 的数据库包装器:https://github.com/illuminate/database。通常,使用经过检查的解决方案比重新发明轮子更好。

【讨论】:

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