Php 致命错误:对中的非对象调用成员函数query()

Php 致命错误:对中的非对象调用成员函数query(),php,pdo,Php,Pdo,我正在使用pdo,并在配置文件中设置了连接字符串,如 $db = new PDO("mysql:host=localhost;dbname=mydbname", 'root', 'pass'); 我在一个类中,在一个方法/函数中有这个查询 $query = $db->query("select aUsername,aPassword,aOnline,aLastlogin from tbl_admins where aUsername = '$username'"); 当我运行我的站点时

我正在使用pdo,并在配置文件中设置了连接字符串,如

$db = new PDO("mysql:host=localhost;dbname=mydbname", 'root', 'pass');
我在一个类中,在一个方法/函数中有这个查询

$query = $db->query("select aUsername,aPassword,aOnline,aLastlogin from tbl_admins where aUsername = '$username'");

当我运行我的站点时,我得到了这个错误。$db对象是否可能不是全局对象?

这不是一种很好的方法,但您应该能够通过向方法/函数中添加全局对象使其工作:

function get_user($username) {
    global $db;
    $query = $db->query("select aUsername,aPassword,aOnline,aLastlogin from tbl_admins where aUsername = '$username'");
    ...
}

以这种方式使用全局变量时,您需要非常小心,不要在任何时候覆盖变量。

这不是一种很好的方法,但您应该能够通过向方法/函数中添加全局变量来使其工作:

function get_user($username) {
    global $db;
    $query = $db->query("select aUsername,aPassword,aOnline,aLastlogin from tbl_admins where aUsername = '$username'");
    ...
}

以这种方式使用全局变量时,您需要非常小心,不要在任何时候覆盖变量。

如果您在全局范围(或函数/方法以外的任何范围)中声明/安装了
$db
,并尝试在函数/方法中使用它,则它将不起作用

如果PDO对象未能实例化或在方法调用之前未设置,则也可能收到此错误。尝试
var_dump(is_object($db))和/或
变量转储($db)以进行检查

您需要执行以下操作之一:


在方法中实例化PDO对象(可能不实用或最佳选项):


在全局范围内实例化PDO对象,并使用
global
关键字将其导入方法:

$db = new PDO( ... );

function foo () {
  global $db;
  $query = $db->query( ... );   
}

在全局作用域中实例化PDO对象,并使用超全局
$GLOBALS
数组访问它

$db = new PDO( ... );

function foo () {
  $query = $GLOBALS['db']->query( ... );   
}

在全局范围内实例化PDO对象,并将其作为参数传递给方法

$db = new PDO( ... );

function foo ($db) {
  $query = $db->query( ... );   
}

foo($db);

在全局范围内实例化PDO对象,并将其作为属性传递到对象中

$db = new PDO( ... );

class foo {

  public $db;

  public function bar ($db) {
    $query = $this->db->query( ... );   
  }

}

$foo = new foo;
$foo->db = $db;
$foo->bar($db);

如果您在全局作用域(或函数/方法以外的任何作用域)中声明/安装了
$db
,并试图在函数/方法中使用它,则它将不起作用

如果PDO对象未能实例化或在方法调用之前未设置,则也可能收到此错误。尝试
var_dump(is_object($db))和/或
变量转储($db)以进行检查

您需要执行以下操作之一:


在方法中实例化PDO对象(可能不实用或最佳选项):


在全局范围内实例化PDO对象,并使用
global
关键字将其导入方法:

$db = new PDO( ... );

function foo () {
  global $db;
  $query = $db->query( ... );   
}

在全局作用域中实例化PDO对象,并使用超全局
$GLOBALS
数组访问它

$db = new PDO( ... );

function foo () {
  $query = $GLOBALS['db']->query( ... );   
}

在全局范围内实例化PDO对象,并将其作为参数传递给方法

$db = new PDO( ... );

function foo ($db) {
  $query = $db->query( ... );   
}

foo($db);

在全局范围内实例化PDO对象,并将其作为属性传递到对象中

$db = new PDO( ... );

class foo {

  public $db;

  public function bar ($db) {
    $query = $this->db->query( ... );   
  }

}

$foo = new foo;
$foo->db = $db;
$foo->bar($db);

我建议使用一个名为的好模式。 以及一个简单的PHP实现:

abstract class Registry {

    private static $_tools = array();

    public static function set($name, $value) {
        self::$_tools[$name] = $value;
    }

    public static function get($name) {
        return (isset(self::$_tools[$name]) ? self::$_tools[$name] : null);
    }

}
用法:

$db = new PDO("mysql:host=localhost;dbname=mydbname", 'root', 'pass');
Registry::set('db', $db);

//In some other part of code
$query = Registry::get('db')->query("select aUsername,aPassword,aOnline,aLastlogin from tbl_admins where aUsername = '$username'");

我建议使用一个名为的好模式。 以及一个简单的PHP实现:

abstract class Registry {

    private static $_tools = array();

    public static function set($name, $value) {
        self::$_tools[$name] = $value;
    }

    public static function get($name) {
        return (isset(self::$_tools[$name]) ? self::$_tools[$name] : null);
    }

}
用法:

$db = new PDO("mysql:host=localhost;dbname=mydbname", 'root', 'pass');
Registry::set('db', $db);

//In some other part of code
$query = Registry::get('db')->query("select aUsername,aPassword,aOnline,aLastlogin from tbl_admins where aUsername = '$username'");


可能地任何上下文都很难说。它是全局的,否则您将收到一个未识别的变量错误。这可能不是PDO的一个实例,为什么或者如何-我不知道。如果错误报告设置为不显示此类警告,您是否在
$db=new PDO(…)
之后重新声明
$db
,但在
$db->query
之前。它可能是未定义的,假设
NULL
,因此是非对象。我会说,您的配置文件实际上应该只包含连接字符串/参数(“mysql:host=localhost;dbname=mydbname”、“root”、“pass”),并且您应该在别处(或需要时)创建PDO对象。可能的话。任何上下文都很难说。它是全局的,否则您将收到一个未识别的变量错误。这可能不是PDO的一个实例,为什么或者如何-我不知道。如果错误报告设置为不显示此类警告,您是否在
$db=new PDO(…)
之后重新声明
$db
,但在
$db->query
之前。它可能是未定义的,假设
NULL
,因此是非对象的。我会说,您的配置文件实际上应该只包含连接字符串/参数(“mysql:host=localhost;dbname=mydbname”、“root”、“pass”),您应该在别处(或需要时)创建PDO对象。+1使用设计模式。但是,如果在PHP中不能同时使用
abstract final
,除非在以后的版本中可以?这会在PHP5.2中触发一个解析错误。您不需要将类声明为
abstract
,而需要一个私有的_construct()方法。祝贺您,您刚刚演示了如何使用设计模式实现全局变量。+1。但是,如果在PHP中不能同时使用
abstract final
,除非在以后的版本中可以?这会在PHP5.2中触发一个解析错误。与其将类声明为
abstract
,您还需要一个私有的_construct()方法。恭喜,您刚刚演示了如何实现一个全局变量。哇,您的权利,我尝试了var_dump(is_object($db));在函数中,它显示为false,但在函数外,它显示为true。有点糟糕,就是这样。但愿我能让它全球化。现在我会像你说的那样在函数中实例化,直到我找到一个更好的方法。@Sarman不幸的是,由于Zend引擎的限制,PHP没有提供声明你自己的超全局的方法,这一点在互联网上已经被讨论过了
$GLOBALS
是最接近可定制超全局的(您可以修改
$\u get
$\u POST
等,但不建议这样做),但它确实会使您的代码更混乱。我有时会做的事情(真正的OO程序员现在把目光移开)是从
$GLOBALS
将数据提取到构造函数中对象的属性中,这样我就不必记得把它作为参数传入了;在函数中,它显示为false,但在