【问题标题】:Keep getting Fatal error: Call to undefined method DB::prepare()不断收到致命错误:调用未定义的方法 DB::prepare()
【发布时间】:2014-10-31 21:54:30
【问题描述】:

这是Reflection::export(new ReflectionClass($this));的回复

Class [ class Users extends Crud ] { 
    @@ C:\xampp\htdocs\classes\Users.php 5-76 
- Constants [0] { 
} 

- Static properties [0] { 
} 

- Static methods [0] {
} 

- Properties [7] {
    Property [ protected $table ]
    Property [ private $username ]
    Property [ private $email ]
    Property [ private $password ]
    Property [ private $passwordRepeat ] 
    Property [ private $nickname ] 
    Property [ private $permission ] 
} 
- Methods [20] {
    Method [ public method setUsername ] {
    @@ C:\xampp\htdocs\classes\Users.php 15 - 17 
- Parameters [1] { 
    Parameter #0 [ $username ] 
} 
} Method [ public method setEmail ] {
    @@ C:\xampp\htdocs\classes\Users.php 19 - 21 
- Parameters [1] {
    Parameter #0 [ $email ] 
} 
} Method [ public method setPassword ] {
    @@ C:\xampp\htdocs\classes\Users.php 23 - 28 
- Parameters [2] { 
    Parameter #0 [ $password ] 
    Parameter #1 [ $passwordRepeat ] 
}
} Method [ public method setNickname ] { 
    @@ C:\xampp\htdocs\classes\Users.php 30 - 32 
- Parameters [1] { 
    Parameter #0 [ $nickname ] 
} 
} Method [ public method setPermission ] {
    @@ C:\xampp\htdocs\classes\Users.php 34 - 36 
- Parameters [1] { 
    Parameter #0 [ $permission ] 
} 
} Method [ public method checkUsername ] {
    @@ C:\xampp\htdocs\classes\Users.php 38 - 49 
- Parameters [2] {
    Parameter #0 [ $username ] 
    Parameter #1 [ $email ] 
} 
} Method [ public method insert ] {
    @@ C:\xampp\htdocs\classes\Users.php 51 - 64
} Method [ public method update ] {
    @@ C:\xampp\htdocs\classes\Users.php 66 - 75 - Parameters [1] {
Parameter #0 [ $id ] 
} 
} Method [ public method find ] {
    @@ C:\xampp\htdocs\classes\Crud.php 12 - 18 
- Parameters [1] {
    Parameter #0 [ $id ] 
} 
} Method [ public method findAll ] {
    @@ C:\xampp\htdocs\classes\Crud.php 20 - 26 
} Method [ public method delete ] { 
    @@ C:\xampp\htdocs\classes\Crud.php 28 - 33 
- Parameters [1] {
    Parameter #0 [ $id ] 
} 
} /** * Create a new DB object for the specified database type but don't * connect to the database * * @param string $type the database type (eg "mysql") * @param array $options an associative array of option names and values * * @return object a new DB object. A DB_Error object on failure. * * @see DB_common::setOption() */ 
Method [ public method &factory ] {
    @@ C:\xampp\php\pear\DB.php 447 - 480 
- Parameters [2] {
    Parameter #0 [ $type ] 
    Parameter #1 [ $options = false ] 
} 
} /** * Create a new DB object including a connection to the specified database * * Example 1. * * require_once 'DB.php'; * * $dsn = 'pgsql://user:password@host/database'; * $options = array( * 'debug' => 2, * 'portability' => DB_PORTABILITY_ALL, * ); * * $db =& DB::connect($dsn, $options); * if (PEAR::isError($db)) { * die($db->getMessage()); * } * * * @param mixed $dsn the string "data source name" or array in the * format returned by DB::parseDSN() * @param array $options an associative array of option names and values * * @return object a new DB object. A DB_Error object on failure. * * @uses DB_dbase::connect(), DB_fbsql::connect(), DB_ibase::connect(), * DB_ifx::connect(), DB_msql::connect(), DB_mssql::connect(), * DB_mysql::connect(), DB_mysqli::connect(), DB_oci8::connect(), * DB_odbc::connect(), DB_pgsql::connect(), DB_sqlite::connect(), * DB_sybase::connect() * * @uses DB::parseDSN(), DB_common::setOption(), PEAR::isError() */ 
Method [ public method &connect ] {
    @@ C:\xampp\php\pear\DB.php 518 - 567 
- Parameters [2] {
    Parameter #0 [ $dsn ] 
    Parameter #1 [ $options = Array ] 
} 
} /** * Return the DB API version * * @return string the DB API version number */ 
Method [ public method apiVersion ] {
    @@ C:\xampp\php\pear\DB.php 577 - 580 
} /** * Determines if a variable is a DB_Error object * * @param mixed $value the variable to check * * @return bool whether $value is DB_Error object */

Method [ public method isError ] {
    @@ C:\xampp\php\pear\DB.php 592 - 595 
- Parameters [1] {
    Parameter #0 [ $value ] 
} 
} /** * Determines if a value is a DB_ object * * @param mixed $value the value to test * * @return bool whether $value is a DB_ object */ 
Method [ public method isConnection ] {
    @@ C:\xampp\php\pear\DB.php 607 - 612 
- Parameters [1] {
    Parameter #0 [ $value ] 
} 
} /** * Tell whether a query is a data manipulation or data definition query * * Examples of data manipulation queries are INSERT, UPDATE and DELETE. * Examples of data definition queries are CREATE, DROP, ALTER, GRANT, * REVOKE. * * @param string $query the query * * @return boolean whether $query is a data manipulation query */ 
Method [ public method isManip ] {
    @@ C:\xampp\php\pear\DB.php 628 - 639 
- Parameters [1] {
    Parameter #0 [ $query ] 
} 
} /** * Return a textual error message for a DB error code * * @param integer $value the DB error code * * @return string the error message or false if the error code was * not recognized */ 
Method [ public method errorMessage ] {
    @@ C:\xampp\php\pear\DB.php 652 - 694 
- Parameters [1] {
    Parameter #0 [ $value ] 
} 
} /** * Parse a data source name * * Additional keys can be added by appending a URI query string to the * end of the DSN. * * The format of the supplied DSN is in its fullest form: * * phptype(dbsyntax)://username:password@protocol+hostspec/database?option=8&another=true * * * Most variations are allowed: * * phptype://username:password@protocol+hostspec:110//usr/db_file.db?mode=0644 * phptype://username:password@hostspec/database_name * phptype://username:password@hostspec * phptype://username@hostspec * phptype://hostspec/database * phptype://hostspec * phptype(dbsyntax) * phptype * * * @param string $dsn Data Source Name to be parsed * * @return array an associative array with the following keys: * + phptype: Database backend used in PHP (mysql, odbc etc.) * + dbsyntax: Database used with regards to SQL syntax etc. * + protocol: Communication protocol to use (tcp, unix etc.) * + hostspec: Host specification (hostname[:port]) * + database: Database to use on the DBMS server * + username: User name for login * + password: Password for login */ Method [ public method parseDSN ] { @@ C:\xampp\php\pear\DB.php 733 - 850 - Parameters [1] { Parameter #0 [ $dsn ] } } /** * Returns the given DSN in a string format suitable for output. * * @param array|string the DSN to parse and format * @param boolean true to hide the password, false to include it * @return string */ 
Method [ public method getDSNString ] {
    @@ C:\xampp\php\pear\DB.php 862 - 926 
- Parameters [2] {
    Parameter #0 [ $dsn ] 
    Parameter #1 [ $hidePassword ] 
}}}} 

Reflection::export(new ReflectionClass('DB')); 我收到以下回复:

Class [ class DB ] { 
    @@ C:\xampp\htdocs\classes\DB.php 5-30 

- Constants [0] { 
} 

- Static properties [1] { 
    Property [ private static $instance ] 
} 

- Static methods [2] { 
    Method [ static public method getInstance ] {
        @@ C:\xampp\htdocs\classes\DB.php 9 - 24 
} 

    Method [ static public method prepare ] { 
        @@ C:\xampp\htdocs\classes\DB.php 26 - 28 - Parameters [1] { 
            Parameter #0 [ $sql ] 
        } 
    } 
} 

- Properties [0] {
 } 

- Methods [0] { 
} }

所以,我是 PHP 新手,我正在尝试学习一点 PDO。 我有这段代码,它一直显示这条消息:

致命错误:在第 22 行调用 C:\xampp\htdocs\classes\Crud.php 中未定义的方法 DB::prepare()

这是我的 DB.php:

<?php

require_once 'cfg.php';

class DB{

private static $instance;

public static function getInstance(){

    if(!isset(self::$instance)){

        try {
            self::$instance = new PDO('mysql:host=' . DB_HOST . ';dbname=' . DB_NAME, DB_USER, DB_PASS);
            self::$instance->setAttribute( PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
            self::$instance->setAttribute(PDO::ATTR_DEFAULT_FETCH_MODE, PDO::FETCH_OBJ);
        } catch (PDOException $e) {
            echo $e->getMessage();
        }

    }

    return self::$instance;
}

public static function prepare($sql){
    return self::getInstance()->prepare($sql);
}

}
?>

Crud.php:

<?php

require_once 'DB.php';

abstract class Crud extends DB {

protected $table;

abstract public function insert();
abstract public function update($id);

public function find($id) {
    $sql = "SELECT * FROM $this->table WHERE ID = :id";
    $qry = DB::prepare($sql);
    $qry->bindParam(':id', $id, PDO::PARAM_INT);
    $qry->execute();
    return $qry->fetch();
}

public function findAll() {
    $sql = "SELECT * FROM $this->table";
    $qry = DB::prepare($sql);
    $qry->execute();
    return $qry->fecthAll();
}

public function delete($id) {
    $sql = "DELETE FROM $this->table WHERE ID = :id";
    $qry = DB::prepare($sql);
    $qry->bindParam(':id', $id, PDO::PARAM_INT);
    return $qry->execute();
}
}
?>

然后,当我尝试从代码中获取任何功能时,我会收到该消息。 例如,如果我尝试这样做:

<?php

$crud = new Users();
$crud->findAll();

?>

Users.php:

<?php

require_once 'Crud.php';

class Users extends Crud {

protected $table = 'bloggy_user';
private $username;
private $email;
private $password;
private $passwordRepeat;
private $nickname;
private $permission;

public function setUsername($username) {
    $this->username = $username;
}

public function setEmail($email) {
    $this->email    = $email;
}

public function setPassword($password, $passwordRepeat) {
    if ($password == $passwordRepeat) {
        $cryptedPass    = password_hash($password, PASSWORD_BCRYPT, ['cost' => 10, 'salt' => '1234567890123456789011']);
        $this->password = $cryptedPass;
    }
}

public function setNickname($nickname) {
    $this->nickname = $nickname;
}

public function setPermission($permission) {
    $this->permission = $permission;
}

public function checkUsername($username, $email) {
    $sql = "SELECT * FROM $this->table WHERE username = :username OR email = :email";
    $qry = DB::prepare($sql);
    $qry->bindParam(':username', $username);
    $qry->bindParam(':email', $email);
    $qry->execute();
    if ($qry->fetchColumn() == 0) {
        return true;
    } else {
        return false;
    }
}

public function insert() {
    $sql = "INSERT INTO $this->table (username, email, password, nickname) VALUES (:username, :email, :password, :nickname)";
    $qry = DB::prepare($sql);
    $qry->bindParam(':username', $this->username);
    $qry->bindParam(':email', $this->email);
    $qry->bindParam(':password', $this->password);
    $qry->bindParam(':nickname', $this->nickname);
    if ($this->checkUsername($this->username, $this->email)) {
        return $qry->execute();
    } else {
        echo "Esse usuário já existe";
        return false;
    }
}

public function update($id) {
    $sql = "UPDATE $this->table SET email = :email, password = :password, nickname = :nickname, permission = :permission WHERE ID = :id";
    $qry = DB::prepare($sql);
    $qry->bindParam(':email', $this->email);
    $qry->bindParam(':password', $this->password);
    $qry->bindParam(':nickname', $this->nickname);
    $qry->bindParam(':permission', $this->permission);
    $qry->bindParam(':id', $id); 
    return $qry->execute();
}
}


?>

它确实显示了错误消息。 如果我说得够清楚的话,我想知道,但我真的是 PDO 的菜鸟,所以如果有人能帮助我,我将不胜感激。

【问题讨论】:

  • Users 类到底在哪里?您遗漏了一些相关数据供我们分析。
  • 你为什么要扩展(或使用...)一个单例?
  • 抱歉,我将编辑并添加用户类
  • 无法复制,见codepad.viper-7.com/rPbe0y;它死于DB 类中的prepare 方法。
  • 但是为什么它在 prepare 方法中死掉了?

标签: php mysql pdo


【解决方案1】:

当我纠正其他错误(见下文)时,代码对我有用。我想知道您的 require_once 是否找到了另一个名为 DB.php 的文件?我将通过在 DB.php 内部但在类定义外部添加类似 print "Hello!"; 的行来测试这一点。然后运行您的脚本并查看您的打印消息是否出现。

如果该消息没有出现,那么您的脚本正在从 require_once 在找到您当前的 DB.php 之前找到的某个不同文件扩展一个 DB 类。如果您有多个相同代码的副本,并且您没有仔细管理您的 PHP include_path,这种错误总是会发生。

如果这样可行,那么您必须有一个没有static function prepare() 的数据库类。您可以将此代码添加到您的脚本中,以找出它认为它具有哪些方法:

    Reflection::export(new ReflectionClass('DB'));

或者在 findAll() 方法中调用 prepare() 之前测试实际的 Crud 对象:

    Reflection::export(new ReflectionClass($this));

好的,我看到了反射导出的输出,我注意到了这一点:

/** * Create a new DB object for the specified database type but don't * connect to the database * * @param string $type the database type (eg "mysql") * @param array $options an associative array of option names and values * * @return object a new DB object. A DB_Error object on failure. * * @see DB_common::setOption() */ 
Method [ public method &factory ] {
    @@ C:\xampp\php\pear\DB.php 447 - 480 
- Parameters [2] {
    Parameter #0 [ $type ] 
    Parameter #1 [ $options = false ] 
} 

注意factory() 方法说它最初是在C:\xampp\php\pear\DB.php 中定义的。而且您的 DB 类的 getInstance() 和 prepare() 方法根本不在那个反射导出中!

所以你的class Crud extends DB实际上是在找到你自己的数据库类之前找到梨DB.php。

这就是 PHP 支持namespaces 的原因,因此您可以确保您的类有一个唯一标识符,即使基类名称与其他一些类冲突。

或者,您也可以将 DB 类重命名为不同的名称,例如 myDBDBconnection 或类似名称。

或者您可以更改您的include_path,以便它在 pear 文件之前找到您的项目文件。

这也解释了为什么代码可以在我的环境中运行,因为我没有使用 XAMPP 或任何其他安装 PEAR 类的东西。


其他错误:

  • 您的 PDO 连接可能会失败,例如由于主机名或用户/密码错误。

  • 如果您不打算纠正根本原因或返回失败,请不要catch() 异常。当您在 getInstance() 中的连接失败时,您会回显错误,但无论如何都会返回该实例。

  • getInstance() 可能不会返回 PDO 对象时,不要调用getInstance()-&gt;prepare()。将其分为两个调用,on 获取实例,第二个调用 prepare() 如果实例作为有效 PDO 对象返回。

    $instance = self::getInstance();
    if ($instance instanceof PDO) {
        return $instance->prepare($sql);
    } else {
        throw new Exception("Not a PDO");
    }
    
  • 您在findAll() 函数中将fetchAll() 拼写为fecthAll()

  • 您调用findAll(),但没有将结果分配给变量。

  • 编辑:我认为"$this-&gt;table" 不起作用,但事实证明我错了,它确实有效。但是您可能仍然需要了解如何在字符串中的变量周围使用花括号来处理其他类型的表达式,例如选择数组元素。

【讨论】:

  • 非常好的点,但我仍然看不到 OP 如何获得提到的错误消息 :-)
  • 对拼写错误的单词和查询进行了更改。但我仍然收到该错误消息。我什至改变了 PDO 连接,所以我不再使用常量,没有任何改变......
  • DB.php 中添加了print "Hello";,但它仍然不起作用。 (它在屏幕上显示Hello)如何在两个通话中分隔getInstance()-&gt;prepare()
  • @LucasPadilha,感谢您进行该测试。总是值得仔细检查。我在上面添加了另一个建议。
  • 已将 DB::prepare() 更改为 $this-&gt;prepare(),它仅从 Call to undefined method DB::prepare() 更改为 Call to undefined method Users::prepare()。我不知道该怎么办!太疯狂了,教程 100% 有效。
猜你喜欢
  • 2013-11-06
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-09-19
  • 2020-02-23
  • 2012-09-25
  • 1970-01-01
相关资源
最近更新 更多