【问题标题】:Yet another 'Call to a member function on a non-object' problem另一个“在非对象上调用成员函数”问题
【发布时间】:2009-12-30 14:10:47
【问题描述】:

我有一个 html 页面,它调用一个 php 对象从数据库中取回一些数据。它工作正常,但脚本变得笨拙,所以我决定将其中的一些分解成一堆函数。

所以我有以下文件:

// htdocs/map.php
<?php
    include("config.php");
    include("rmap.php");

    $id = 1;
    $gamenumber = getGameNumber($id);
    echo $gamenumber;
?>

// htdocs/config.php
<?php
$_PATHS["base"]      = dirname(dirname(__FILE__)) . "\\";
$_PATHS["includes"]  = $_PATHS["base"] . "includes\\";

ini_set("include_path", "$_PATHS[includes]");
ini_set("display_errors", "1");
error_reporting(E_ALL); 

include("prepend.php");
?> 

// includes/prepend.php
<?php
include("session.php");
?>

// includes/session.php
<?php
includes("database.php");

class Session {
    function Session() {
    }

};

$session = new Session;
?>

// includes/database.php
<?php
include("constants.php");

class Database {

    var $connection;

    function Database() {
        $this->connection = mysql_connect(DB_SERVER, DB_USER, DB_PASS) or die(mysql_error());
        mysql_select_db(DB_NAME, $this->connection) or die(mysql_error());
    }

    function query($query) {
        return mysql_query($query, $this->connection);
    }
};

/* Create database connection */
$database = new Database;
?>

// includes/rmap.php
<?php
function getGameNumber($id) {
    $query = "SELECT gamenumber FROM account_data WHERE usernum=$id";
    $result = $database->query($query); // line 5
    return mysql_result($result, 0);
}
?>

常量中有一堆定义(DB_USER 等)。

所以,map.php 包含 config.php。这又包括 prepend.php,其中包括 session.php 和包括 database.php。 map.php 还包括 rmap.php,它尝试使用 database 对象。

问题是我得到了一个

致命错误:在非对象上调用成员函数 C:\Develop\map\includes\rmap.php 在第 5

通常的原因是 $database 对象没有被创建/初始化,但是如果我添加代码来显示当(通过echo "DB connection created";echo "using DB connection";)它们被调用(或至少显示) 以正确的顺序。

如果我将include("database.php") 添加到 rmap.php,我会收到有关重新定义 constants.php 内容的错误。如果我使用require_once,我会得到与以前相同的错误。

我在这里做错了什么?

【问题讨论】:

  • 如果我可以在问题上附加一个小 zip 文件会容易得多。
  • 你真的在使用 PHP4 和 MySQL3 吗?如果是这样,你真的真的需要升级。他们都9岁了!
  • 好的,给我们一个简单的方法来升级而不破坏任何东西,我们会做到的。
  • 只有傻瓜才会需要一种万无一失的方法,我怀疑你不是;-] 此外,VirtualBox 和旧计算机的存在是有原因的! (如果不清楚,可用作测试服务器)
  • 说到 Linux,我需要一个万无一失的方法:-) 这是一个非标准的 linux 安装,软件是以非常非传统的方式编写的。

标签: php mysql php4


【解决方案1】:

$database不在函数GetGameNumber的作用域内。

最简单但不一定是最好的解决方案是

<?php
function getGameNumber($id) {
    global $database;  // added this
    $query = "SELECT gamenumber FROM account_data WHERE usernum=$id";
    $result = $database->query($query); // line 5
    return mysql_result($result, 0);
}
?>

global 被认为是不完美的,因为它违反了 OOP 的原则,并且据说对性能有一些影响,因为全局变量及其所有成员都添加到函数的作用域中。不过,我不知道这对性能有多大影响。

如果你想解决这个问题,我不久前asked a question on how to organize such things 得到了一些很好的答案和链接。

【讨论】:

  • 所以如果我有 20 个函数都需要 '$database',我必须将 'global $database' 添加到所有这些函数中吗?为什么 '$database' 不是全球性的?
  • $database 全局的,但函数和方法的范围默认不包括全局范围的变量。它们在孤立的范围内执行。 (出于安全原因,我假设) - 避免必须包含全局变量的一个好方法是使用 Singleton 类。所以你可以这样做:$result = Database::Get()-&gt;query($query);,或者简化为$result = Database::query($query);
  • 你也可以像这样访问 $database:$GLOBALS["database"] 但我发现这比global $varname; 更烦人
【解决方案2】:

你需要包含

global $database;

getGameNumber() 的顶部,因为$database 是在getGameNumber 本身之外定义的

【讨论】:

    【解决方案3】:

    您的$database 变量无法从函数范围自动访问。您可能需要在函数中将其声明为global $database;

    PHP 中的作用域在文档中进行了解释:http://de3.php.net/manual/en/language.variables.scope.php

    还请注意,PHP 4 和 MySQL3 在很长一段时间内都不再支持,并且可能包含安全问题和其他未修复的问题。

    【讨论】:

    • 是的,但我不会重写所有内容。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2014-02-02
    • 2010-09-26
    • 2012-04-20
    • 2015-05-01
    • 2014-08-07
    • 2013-12-01
    • 2015-12-23
    相关资源
    最近更新 更多