【问题标题】:Scope error - Call to a member function prepare() on a non-object范围错误 - 在非对象上调用成员函数 prepare()
【发布时间】:2011-06-22 02:24:27
【问题描述】:

所以场景很简单。我使用在数据库中执行某些操作的类,但在该类中我调用了另一个也在 DB 中执行某些操作的类。

谢谢,include_once 更改为包含,它可以工作!

这是我得到的:

致命错误:调用成员函数 prepare() 在非对象上 -> mLog.php 在第 20 行

我使用 db_config.php 创建 PDO 对象,然后将其包含在我的类中。

db_config.php

try
{
    $DBH = new PDO("mysql:host=$db_host;dbname=$db_name", $db_user, $db_pass);

    $DBH->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_WARNING);
}
catch (PDOException $e)
{
    echo $e->getMessage();
}

一级 mLog.php

<?php

    class Log
    {
        public static function Add($action)
        {
            try
            {
                include_once "db_config.php";

                $ip = $_SERVER['REMOTE_ADDR'];

                $time = date('Y-m-d');

                $values = array($ip, $action, $time);
//ERROR NEXT LINE
                $STH = $DBH->prepare("INSERT INTO log (ip, action, time)
                                      VALUES (?, ?, ?)");

                $STH->execute($values);

                $DBH = null;
                $STH = null;
            }
            catch (PDOException $e)
            {
                echo $e->getMessage();
            }
        }
    }

第二类使用第一类(片段,因为它很大并且有很多功能)

public static function Add($catName, $catDescr = "", $catImgURL = "", $catSubLevel = 0, $catSubID = 0)
{
    try
    {
        include_once "db_config.php";
        include_once "mLog.php";

        $values = array($catName, $catDescr, $catImgURL, $catSubLevel, $catSubID);
        $STH = $DBH->prepare("INSERT INTO cat (catName, catDescr, catImg, catSubLevel, catSubID)
                              VALUES (?, ?, ?, ?, ?)");

        $STH->execute($values);

        $DBH = null;
        $STH = null;

        //HERE IT IS
        Log::Add("Added category 111" . $catName);

        return true;
    }
    catch (PDOException $e)
    {
        echo $e->getMessage();
    }
}

【问题讨论】:

  • 错误还应该有一个文件和行号。这对应什么?在 Log 类或第二类中的 prepare() 调用?

标签: php pdo


【解决方案1】:

您使用了include_once "db_config.php"; 而不是include "db_config.php";

我从您的代码中了解到,每次包含db_config.php 时,您都会创建数据库对象$DBH

由于你把它设置为include_once,它只会运行一次db_config.php,并且在你尝试包含它的日志类中,它不会运行-因为它已经包含在Add方法中。

为了改进这一点,您应该创建一个单独管理(或封装)PDO 对象的类。您可以简单地创建一个返回 PDO 对象的 Singleton 类,将该类包含在顶部一次,然后在代码中的任何位置获取该对象。

例子:

DBAccess.php

class DBAccess extends Singleton{

    // there is a getInstance() method in the Singleton abstract class

    private $dbh;

    // The PDO object is created only once when the first getInstance() is called in Singleton.
    function __construct(){
        try
        {
            $this->dbh = new PDO("mysql:host=$db_host;dbname=$db_name", $db_user, $db_pass);

            $this->dbh->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_WARNING);
        }
        catch (PDOException $e)
        {
            echo $e->getMessage();
        }

    }

    /**
     * Get the PDO object
     * @return object
     */
    public static function getDBH(){
        return self::getInstance()->dbh;
    }

}

日志类:

class Log
{
    public static function Add($action)
    {
        try
        {
            $DBH = DBAccess::getDBH();

            $ip = $_SERVER['REMOTE_ADDR'];

            $time = date('Y-m-d');

            $values = array($ip, $action, $time);

            $STH = $DBH->prepare("INSERT INTO log (ip, action, time)
                                  VALUES (?, ?, ?)");

            $STH->execute($values);
        }
        catch (PDOException $e)
        {
            echo $e->getMessage();
        }
    }
}

用法:

include_once('db_config.php'); include_once('mLog.php');

public static function Add($catName, $catDescr = '', $catImgURL = '', $catSubLevel = 0, $catSubID = 0)
{
    try
    {

        $DBH = DBAccess::getDBH();

        $values = array($catName, $catDescr, $catImgURL, $catSubLevel, $catSubID);

        $STH = $DBH->prepare("INSERT INTO cat (catName, catDescr, catImg, catSubLevel, catSubID)
                              VALUES (?, ?, ?, ?, ?)");

        $STH->execute($values);

        $DBH = null;

        Log::Add("Added category 111" . $catName);

        return true;
    }
    catch (PDOException $e)
    {
        echo $e->getMessage();
    }
}

【讨论】:

  • 好吧,这对我有帮助,现在可以了。但我想知道这是一种很好的做事方式。就像每次包含 $DBH 对象时都创建它...
  • 不是。我将在我的答案的下一次编辑中向您展示我如何在我正在开发code.google.com/p/phpraise 的框架中做到这一点。
  • 是的,这个想法我很清楚,但是我对单例类有一些问题
  • 您可以随时在 Stack Overflow 上提出其他具体问题 =)
  • 是的,我做到了,:) stackoverflow.com/questions/4914302/…
【解决方案2】:

$DB 的范围不在类中,因为您没有将它传递到类中。目前它只是在全局范围内浮动,但不在您的类范围内。

您需要将$DB 添加到Log 类中,您可以像在db_config.php 中那样将其作为静态变量来完成

Log::$DB = $DB;

在你的课堂上像这样使用

class Log
{
    public static $DB;

    public static function Add($action)
    {
        try
        {
            include_once "db_config.php";

            $ip = $_SERVER['REMOTE_ADDR'];

            $time = date('Y-m-d');

            $values = array($ip, $action, $time);
            $STH = self::$DBH->prepare("INSERT INTO log (ip, action, time)
                                  VALUES (?, ?, ?)");

            $STH->execute($values);

            self::$DBH = null;
            $STH = null;
        }
        catch (PDOException $e)
        {
            echo $e->getMessage();
        }
    }
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-05-22
    • 2015-12-30
    相关资源
    最近更新 更多