tags:

views:

336

answers:

3

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?

+2  A: 

$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.

Pekka
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
`$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
You can also access $database like so: `$GLOBALS["database"]` but I find that more annoying than `global $varname;`
Pekka
A: 

You need to include

global $database;

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

Wim
A: 

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
Yeah, but I am not going to rewrite everything.
graham.reeds