Jump to content


Photo

Database abstraction layer not passing variables.


  • Please log in to reply
8 replies to this topic

#1 maddog39

maddog39
  • New Members
  • Pip
  • Newbie
  • 7 posts

Posted 28 October 2006 - 07:47 PM

Hello all,

I am coding a custom DBAL for my site and I am having tons of issues making it pass this one global clas variable, for some reason it keeps getting erased from memory after the first function. I have posted a section of my class that has so far been giving me the most problems.

class db {
	var $db;
	var $db_type;
    var $sql;

    function init($dbhost, $dbtype, $dbuser, $dbpass, $dbname) {
        if (!isset($dbhost)) {
            echo "database::init(): No database host set.";
            exit();
        }
		elseif (!isset($dbtype)) {
			echo "database::init(): No database type set.";
			exit();
		}
        elseif (!isset($dbuser)) {
            echo "database::init(): No database username set.";
            exit();
        }
        elseif (!isset($dbpass)) {
            echo "database::init(): No database password set.";
            exit();
        }
        elseif (!isset($dbname)) {
            echo "database::init(): No database name set.";
            exit();
        }
		switch ($dbtype) {
		case "mysql":
			$mysql_connect = @mysql_connect($dbhost, $dbuser, $dbpass);
			$mysql_select_db = @mysql_select_db($dbname);
			if ((!$mysql_connect) || (!$mysql_select_db)) {
				echo "database::init(): Database Error:<br>" . mysql_error();
				exit();
			}
			$this->db_type = $dbtype;
			break;
		case "postgresql":
			$this->db = @pg_connect("host={$dbhost} dbname={$dbname} user={$dbuser} pass={$dbpass}");
			if (!$this->db) {
				echo "database::init(): Database Error:<br>" . pg_last_error($this->db);
				exit();
			}
			$this->db_type = $dbtype;
			break;
		case "sqlite":
			$this->db = @sqlite_open($dbname);
			if (!$this->db) {
				echo "database::init(): Database Error:<br>" . sqlite_error_string(sqlite_last_error($this->db));
				exit();
			}
			$this->db_type = $dbtype;
			break;
		default:
			echo "database::init(): No database type set.";
			exit();
			break;
		}
    }
    function query($sql) {
        if (!isset($sql)) {
            echo "database::query(): No SQL code set.";
            exit();
        }
		elseif (!isset($this->db_type)) {
			echo "database::query(): No database type set.";
			exit();
		}
        if (is_array($sql)) {
            foreach ($sql as $key => $value) {
				switch ($this->type) {
				case "mysql":
					$this->sql['$key'] = mysql_query($value);
					if (!$this->sql['$key']) {
						echo "database::query(): Database Error:<br>" . mysql_error();
						exit();
					}
					return $this->sql['$key'];
					break;
				case "postgresql":
					$this->sql['$key'] = pg_query($this->db, $value);
					if (!$this->sql['$key']) {
						echo "database::query(): Database Error:<br>" . pg_result_error($this->db);
						exit();
					}
					return $this->sql['$key'];
					break;
				case "sqlite":
					$this->sql['$key'] = sqlite_query($this->db, $value);
					if (!$this->sql['$key']) {
						echo "database::query(): Database Error:<br>" . sqlite_error_string(sqlite_last_error($this->db));
						exit();
					}
					return $this->sql['$key'];
					break;
				}
            }
        } else {
            switch ($this->db_type) {
			case "mysql":
				$this->sql = mysql_query($sql);
				if (!$this->sql) {
					echo "database::query(): Database Error:<br>" . mysql_error();
					exit();
				}
				return $this->sql;
				break;
			case "postgresql":
				$this->sql = pg_query($this->db, $sql);
				if (!$this->sql) {
					echo "database::query(): Database Error:<br>" . pg_result_error($this->db);
					exit();
				}
				return $this->sql;
				break;
			case "sqlite":
				$this->sql = sqlite_query($this->db, $sql);
				if (!$this->sql) {
					echo "database::query(): Database Error:<br>" . sqlite_error_string(sqlite_last_error($this->db));
					exit();
				}
				return $this->sql;
				break;
			}
        }
    }
When I call function init(), its supposed to connect to the database according to which database system I am using from the $dbtype parameter. Then I take $dbtype and put it into the global class variable $this->db_type, and this is the part that just doesn't make ANY sense. When I go and call the function query(), I get an error message from my error checking system in each function that says, no database type was set, and I do some tests like try to echo each variable and stuff. $this->db_type works in init() but it seems to be cleared when used in query() and there isnt any data in the variable when I try to use it in another function. Now, I dont know but this problem most likely also applies to all the other functions in my class. Can someone PLEASE help!?

Thanks alot!
-maddog39

#2 toplay

toplay
  • Staff Alumni
  • Advanced Member
  • 973 posts

Posted 28 October 2006 - 08:05 PM

Do you happen to be calling query() with an array? because the line under the foreach in query() has:

switch ($this->type) {

when it should be:

switch ($this->db_type) {


Also, you need to take out the single quote from:

$this->sql['$key']

and just use:

$this->sql[$key]



#3 maddog39

maddog39
  • New Members
  • Pip
  • Newbie
  • 7 posts

Posted 28 October 2006 - 08:39 PM

I have tested this class without multi-db type support and it didnt work originally when I used

$this->sql[$key]

So I added the single quotes. Nice catch on that bug though but I am not running queries in an array in this case. The error the class is returning is:

database::query(): No database type found.

So, the db_type variable isnt being passed, I even tried echoing it in both init() and query() and it works in init() but it seems the variable is cleared in query() because there's no data in it?

#4 toplay

toplay
  • Staff Alumni
  • Advanced Member
  • 973 posts

Posted 28 October 2006 - 08:52 PM

Please show us the code on how you're instantiating and calling init() and query().

If you use single quotes with a variable name in it, then it will not be recognized as a variable but taken literally. Example:

$key = '200';

echo 'var value: $key';  // displays: var value: $key
echo "var value: $key";  // displays: var value: 200

That's why I mentioned you can use $this->sql[$key], or use $this->sql["$key"].

See this section of the manual for more info:
http://us3.php.net/m....string.parsing

FYI - isset() will return false when variable is set with a value but happens to be NULL.


#5 maddog39

maddog39
  • New Members
  • Pip
  • Newbie
  • 7 posts

Posted 28 October 2006 - 09:04 PM

Okay, $this->sql is an array though, so I think that differs from if your use it in echo as you showed me. But I can't confirm that so ill try it both ways once I get the db_type problem fixed. Also I use isset() because the variable needs to be set and have a meaningful value, meaning, cant be null. Here is the code from my tempalting system that I believe is the one having problems with query() because its the first thing that needs to access the database on my index.

class template extends db {
	var $tpl_tid;
	var $tpl_name;
	var $tpl_htmlcode;
	var $tpl_cleancode;
	var $tpl_variables;
	
	function init($theme_name) {
		if (!isset($theme_name)) {
			echo "template::init(): No theme name specified.";
			exit();
		}
		$this->tpl_name = $theme_name;
	}
	function getdata($handle) {
		if (!isset($handle)) {
			echo "template::getdata(): No handle was specified.";
			exit();
		}
		elseif (!isset($this->tpl_name)) {
			echo "template::getdata(): No theme name specified.";
			exit();
		}
		$query = $this->db->query("SELECT * FROM {$config['dbprefix']}templates WHERE title='$handle' AND theme='{$this->tpl_name}' LIMIT 1");
		$data = $this->fetch_array($query);
		$this->tpl_tid = $data['tid'];
		$this->tpl_htmlcode[$handle] = $data['code'];
    }


#6 toplay

toplay
  • Staff Alumni
  • Advanced Member
  • 973 posts

Posted 28 October 2006 - 09:11 PM

In the recent code posted I don't see where you're instantiating the db class and calling the init() method.

All I see is you trying to call query() and of course $this->db_type will be null (because of my above comment).


#7 maddog39

maddog39
  • New Members
  • Pip
  • Newbie
  • 7 posts

Posted 28 October 2006 - 09:22 PM

Well, there is an included file called global.php which has initilizes all major application data, for example stuff from the config file. The way I am execing this is from index.php, and this is how the file structure looks.

index.php
config.php
Folder: includes
---- global.php
---- class_database.php
---- class_template.php

Excerpt from global.php

include_once("./config.php");

// Get and include core files
$includes = array(
	"class_database",
	"class_core",
	"class_template",
	"class_theme",
	"class_paginate"
);
foreach ($includes as $file_name) {
  	$file = $config['includes_path'] . $file_name . ".php";
  	if (file_exists($file)) {
	    include_once($file);
	} else {
	  	echo "File not found.<br>";
	}
}

$db->init($config['dbhost'], $config['dbtype'], $config['dbuser'], $config['dbpass'], $config['dbname']);
$template->init("default");


#8 toplay

toplay
  • Staff Alumni
  • Advanced Member
  • 973 posts

Posted 28 October 2006 - 09:49 PM

There are a few things that are wrong or could be done better. I suggest you read and learn more on PHP OOP approaches.

Some things for you to look at, think about, or answer for yourself:

Where is either the db or template class being instantiated and assigned to $db?

Why am I extending a template class based on a database class?

What happens if I extend a class and I use the same method name as in the parent (i.e. init method)?

Is it a good idea to put all database types into one class, or can I do it in another more efficient way? hint: one class per database type, and have a database connection factory.




#9 maddog39

maddog39
  • New Members
  • Pip
  • Newbie
  • 7 posts

Posted 28 October 2006 - 09:55 PM

Well, what I'm trying to do is have other classes be able to use the database class, for sole reason of having the ability to use different database engines and dynamically use different functions accordingly. Now when I try to use the functions in the database class normally without extending I get an error saying, "non-existant object query() in ........" thats when I discovered I could probably use extends to fix that. Thats where I'm stuck.




0 user(s) are reading this topic

0 members, 0 guests, 0 anonymous users