0

I have a html page that calls a php object to get some data back from the database. It works fine, but the script was getting unwieldy so I decided to break some of it out into a bunch of functions.

So I have the following files:

// 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);
}
?>

And constants has a bunch of defines in it (DB_USER, etc).

So, map.php includes config.php. That in turn includes prepend.php which includes session.php and that includes database.php. map.php also includes rmap.php which tries to use the database object.

The problem is I get a

Fatal error: Call to a member function on a non-object in C:\Develop\map\includes\rmap.php on line 5

The usual cause of this is that the $database object isn't created/initialised, but if I add code to show which gets called when (via echo "DB connection created"; and echo "using DB connection";) they are called (or at least displayed) in the correct order.

If I add include("database.php") to rmap.php I get errors about redefining the stuff in constants.php. If I use require_once I get the same errors as before.

What am I doing wrong here?

skaffman
  • 398,947
  • 96
  • 818
  • 769
graham.reeds
  • 16,230
  • 17
  • 74
  • 137
  • It would be so much easier if I could attach a small zip file to the problem. – graham.reeds Dec 30 '09 at 14:11
  • Are you really using PHP4 and MySQL3? If so, you really *really* need to upgrade. They are both like 9 years old! – Atli Dec 30 '09 at 14:34
  • Okay, give us an fool-proof way to upgrade without breaking anything and we'll do it. – graham.reeds Dec 30 '09 at 14:45
  • Only a fool would need a fool-proof way, which I suspect you are not ;-] Besides, VirtualBox and old computers exist for a reason! *(To be used as test servers, if that wasn't clear)* – Atli Dec 30 '09 at 14:50
  • When it comes to Linux I need a fool-proof way:-) It's a non-standard linux install and the software was written in a very non-conventional way. – graham.reeds Dec 30 '09 at 16:36

3 Answers3

2

$database is not in the scope of function GetGameNumber.

The easiest, though not necessarily best, solution is

<?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 is deemed not perfect because it violates the principles of OOP, and is said to have some impact on performance because a global variable and all its members are added to the function's scope. I don't know how much that really affects performance, though.

If you want to get into the issue, I asked a question on how to organize such things a while back and got some good answers and links.

Community
  • 1
  • 1
Pekka
  • 442,112
  • 142
  • 972
  • 1,088
  • So if I have 20 functions which all require '$database', I have to add 'global $database' to all of them? And why isn't '$database' global as it is? – graham.reeds Dec 30 '09 at 14:38
  • `$database` *is* global, but the scope of functions and methods does not include variables from the global scope by default. They are executed in an isolated scope. *(For security reasons, I would assume)* - A good way to get around having to include global variables is to use Singleton classes. So you could do: `$result = Database::Get()->query($query);`, or simplified as `$result = Database::query($query);`. – Atli Dec 30 '09 at 15:51
  • You can also access $database like so: `$GLOBALS["database"]` but I find that more annoying than `global $varname;` – Pekka Dec 30 '09 at 16:25
0

You need to include

global $database;

at the top of getGameNumber(), since $database is defined outside of getGameNumber itself

Wim
  • 11,091
  • 41
  • 58
0

Your $database varibleis not accessible from the function's scope automatically. You might need to declare it as global $database; in the function.

Scopes in PHP are explained in the documentation: http://de3.php.net/manual/en/language.variables.scope.php

Please also mind that PHP 4and MySQL3 are out of support for a looooong time and might contain security problems and other unfixed issues.

johannes
  • 15,807
  • 3
  • 44
  • 57