Jump to content

Classes related error


CK9

Recommended Posts

Hello again!

 

I've been trying out new things (well, new for me) in php again.  This time I decided to try a real challenge and make a forum system.  A friend suggested I use a class for all database functionalities.  i was reluctant at first, but decided if I was going to try using classes for the first time, it might as well be with this.  With some guiding help, I set up the files and gave it a visual once over to check for errors.  Nothing seemed out of place, but when I loaded the page to try it out, I got this error:

 

Fatal error: Call to a member function query() on a non-object in /home/ck9/public_html/planning/forumbuild/list.php on line 20

 

I didn't see anything out of line, so I consulted my friend about it.  He made a few small adjustment suggestions, but nothing fixed the issue.  I then bugged my host about it, and he couldn't find anything wrong either.  Both people are highly experienced in php, so when they say it SHOULD be working I am left rather confused.

 

Here is list.php:

<?php
include("db.class.php");
include("db.config.php");

$db = new databaseConnection($config['user'],$config['pass'],$config['database']);
$g = $_GET['g'];
$s = $_GET['s'];
$t = $_GET['t'];

function tablestart($a = '1')
  {
   global $db;

   echo "<table border='" . $a . "' cellpadding='10' cellspacing='0' align='center' width='80%' style='color: #C0C0C0'>\n";
  }
function contents($table, $a, $b = '1', $c = '1')
  {
   global $db;

   $db->query("SELECT * FROM $table");

   while($row = $db->fetch_array())
    {
     if($row['level'] <= $_SESSION['ulevel'])
      {
       echo "<tr><td width='5%'><!--indicator--></td><td width='80%'><a href='index.php?pg=h&g='" . $row['g'];
       if(($a > '1') && ($row['g'] == $b))
        {
         echo "&s=" . $row['s'];
         if(($a > '2') && ($row['s'] == $c))
          {
           echo "&t=" . $row['t'];
          }
        }
      }
     echo "' style='color: #C0C0C0 ; text-decoration: none'><font size='4'>" . $row['name'] . "</font><br /><fpnt size='3'>" . $row['desc'] . "</td><td width='15%'><!--last update--></td></tr>\n";
    }
  }

if(empty($_SESSION['ulevel']))
  {
   $_SESSION['ulevel'] = '0';
   echo "<font color='#CC0000'><center>You need to register to post in these forums.</center></font><br />\n";
  }

if(empty($g))
  {
   tablestart();
   contents('group', '1');
   echo "</table>\n";
  }
elseif(empty($s))
  {
   tablestart();
   contents('section', '2', $g);
   echo "</table>\n";
  }
elseif(empty($t))
  {
   tablestart('0');
   echo "<tr><td width='80%'></td><td><!--new topic--></td></tr>\n</table>\n";
   tablestart();
   contents('topic', '3', $g, $s);
   echo "</table>\n";
  }
elseif(!empty($t))
  {
   tablestart('0');
   echo "<tr><td width='80%'></td><td><!--new topic and reply--></td></tr>\n</table>\n";
   $data = file_get_contents('topics/g' . $g . 's' . $s . 't' . $t . '.txt');
   $post = explode("<!--p-->", $data);
   $length = count($post);
   tablestart('1');
   for($z = '0'; $z < $length; $z ++)
    {
     $i = '0';
     $cont = explode("<!--e-->", $post[$pos]);
     echo "<tr><td><b>" . $cont[$i] . "</b><br /><!--future additions--></td><td>\n<table width='100%' style='font-size: xx-small'>\n<tr><td height='3' width='75%'>";
     $i ++;
     echo "Posted on" . $cont[$i] . "</td><td height='3' width='25%'><!--future additions--></td></tr><tr><td width='100%'>";
     $i ++;
     echo $cont[$i] . "</td></tr></table></td></tr>\n";
    }
   echo "</table>\n";
  }
?>

 

My aim here was to have a single page to display the groups, sections, topics, and posts in order to keep database calls where I could find them easily.

 

and here is the class file:

 

<?php
class databaseConnection
{
  protected $link;
  protected $lastResult;
  function databaseConnection($user,$pass,$database)
   {
    $this->link = mysql_connect("localhost",$user,$pass);
    if( !$this->link )
     {
      die('Vital information missing.');
     }
    else
     {
      mysql_select_db($database,$this->link) or die('could not find database: ' . mysql_error());
     }
   }
  function query($query)
   {
    $this->lastresult = mysql_query($query) or die('MySQL error: ' . mysql_error());
    return $this->lastresult;
   }
  function fetch_array($result = false)
   {
    if(!$result)
     {
      return mysql_fetch_array($this->lastresult);
     }
    else
     {
      return mysql_fetch_array($result);
     }
   }
}
?>

 

I have tried everything from adjusting the php tags to putting the class directly in the page.

 

The config file just provides the user, pass, and which database to connect to.  I've checked it's formatting a few times just in case.

Link to comment
Share on other sites

PHP is saying $db is not an object - what is it then?  I would use var_dump() to show what is in $db before it is assigned, after it is assigned (after line 5 of list.php), and just before it is used in contents().  Once you've confirmed that it is correct after it is created but incorrect when used in contents(), start checking its value in between the points where you have already checked it, to find where it changes.

Link to comment
Share on other sites

Okay, I did that and because of my lack of formal education in PHP, I'm left scratching my head a bit further

 

NULL object(databaseConnection)#1 (2) { ["link:protected"]=> resource(7) of type (mysql link) ["lastResult:protected"]=> NULL }

 

NULL

 

I'm assuming that one of the class functions is causing it to revert back to a NULL variable.  Looking through my class file, my attention is drawn to the followig lines:

 

  protected $link;
  protected $lastResult;

 

and

 

  function query($query)
   {
    $this->lastresult = mysql_query($query) or die('MySQL error: ' . mysql_error());
    return $this->lastresult;
   }
  function fetch_array($result = false)
   {
    if(!$result)
     {
      return mysql_fetch_array($this->lastresult);
     }
    else
     {
      return mysql_fetch_array($result);
     }
   }

 

So, the function cannot execute because the protected status is preventing the list.php code from making a new entry (for lack of a better term) using the class.  Am I at least close to correct?

Link to comment
Share on other sites

I'm assuming that one of the class functions is causing it to revert back to a NULL variable

 

Ok this is the key finding - $db was an object after it got instantiated, but later it's not an object anymore, it's null.  I don't think protected has anything to do with it, because protected class members may be accessed from within the class itself.  And, if that were the issue, you would get an error instead of $db being set to null.  If you want to eliminate this as a cause, just declare them both public instead.

 

Another probably minor issue - $lastResult is not the same as $lastresult.

 

What I would do is start displaying the contents of $db in more locations, so you can pinpoint exactly where it changes from an object to null.  You might want to tag each location as well, eg:

 

print "<pre> Before checking SESSION[ulevel]: " ; var_dump($db) ; print "</pre>";

 

The "pre" tags will make the output more readable.

 

Eventually you will narrow it down to a single line.  Before that line, $db is an object.  After that line, $db is null.  And that's the line you need to fix.

Link to comment
Share on other sites

Okay, after adding it in several places, it would seem the second I'm inside the first function on list.php (tablestart), it's null...even before the "global $db;" line

 

I see no reason for a function to cause this...

Link to comment
Share on other sites

It SHOULD be null before the global $db line.  After global $db, it should be an object.  The line "global $db;" is where $db is brought from global scope (ie outside all the functions) into local scope (ie inside the function).  Is it still null after that line?

 

 

Link to comment
Share on other sites

It doesn't work because it then ignores the inclusion of the config file

 

Warning: mysql_connect() [function.mysql-connect]: Access denied for user 'nobody'@'localhost' (using password: NO) in /home/ck9/public_html/planning/forumbuild/db.class.php on line 8

Vital information missing.

Link to comment
Share on other sites

Line 8 of class file:

 

    $this->link = mysql_connect("localhost",$user,$pass);

 

code for config file (info replaced with blank space):

 

<?php
$config = array( "user" => " ", "pass" => " ", "database" => " ");
?>

Link to comment
Share on other sites

Try your var_dump tests inside the functions again but DO NOT put the var_dump BEFORE the global command. I suspect that calling var_dump($db) BEFORE global, defines a new variable called $db because you have referenced it. Since you are "defining" it without assigning a value it is NULL.

 

Leave the var_dump AFTER the global, and see what it tells us.

Link to comment
Share on other sites

CK9, can you please post the full code.  Snippets are not useful, because the important thing here is the order in which code is executed.  Can you please post the full code of any file modified since you originally posted, along with the errors that code currently gives.

 

The db config file looks innocent enough.

Link to comment
Share on other sites

Currently, all the page codes are the same as posted in the first post (and whichever number the config code is in).  I haven't done anything to permanantly modify the code.  After running the test with the value dump lines, I removed them in order to keep the code the same as what is seen in this topic so that suggestions could be more quickly tested.

Link to comment
Share on other sites

Ok, can you please make the following changes

 

 function tablestart($a = '1')
  {
   global $db;

 

to

 

 function tablestart($db, $a = '1')
  {

 

And also change every call to tablestart() as follows:

 

tablestart()
replace with
tablestart($db)

tablestart('0')
replace with
tablestart($db, '0')

 

I don't know what you did when I asked you to make $db an argument to those functions, but this is what I was wanting you to do.  It's got nothing to do the db config file or where $db is set to a new class instance.

Link to comment
Share on other sites

I had added the "$db->..." into the second function rather than adding $db as an argument....  After reviewing the code again, I realized the first itteration of the global variable (inside the tablestart function) was a placement error that I only partially corrected, so that gets removed entirely...

 

Here's what I have now:

 

<?php
include("db.class.php");
include("db.config.php");

$db = new databaseConnection($config['user'],$config['pass'],$config['database']);
$g = $_GET['g'];
$s = $_GET['s'];
$t = $_GET['t'];

function tablestart($a = '1')
  {
   echo "<table border='" . $a . "' cellpadding='10' cellspacing='0' align='center' width='80%' style='color: #C0C0C0'>\n";
  }
function contents($db, $table, $a, $b = '1', $c = '1')
  {
//   global $db;

   $db->query("SELECT * FROM $table");

   while($row = $db->fetch_array())
    {
     if($row['level'] <= $_SESSION['ulevel'])
      {
       echo "<tr><td width='5%'><!--indicator--></td><td width='80%'><a href='index.php?pg=h&g='" . $row['g'];
       if(($a > '1') && ($row['g'] == $b))
        {
         echo "&s=" . $row['s'];
         if(($a > '2') && ($row['s'] == $c))
          {
           echo "&t=" . $row['t'];
          }
        }
      }
     echo "' style='color: #C0C0C0 ; text-decoration: none'><font size='4'>" . $row['name'] . "</font><br /><fpnt size='3'>" . $row['desc'] . "</td><td width='15%'><!--last update--></td></tr>\n";
    }
  }

if(empty($_SESSION['ulevel']))
  {
   $_SESSION['ulevel'] = '0';
   echo "<font color='#CC0000'><center>You need to register to post in these forums.</center></font><br />\n";
  }

if(empty($g))
  {
   tablestart();
   contents($db, 'group', '1');
   echo "</table>\n";
  }
elseif(empty($s))
  {
   tablestart();
   contents($db, 'section', '2', $g);
   echo "</table>\n";
  }
elseif(empty($t))
  {
   tablestart('0');
   echo "<tr><td width='80%'></td><td><!--new topic--></td></tr>\n</table>\n";
   tablestart();
   contents($db, 'topic', '3', $g, $s);
   echo "</table>\n";
  }
elseif(!empty($t))
  {
   tablestart('0');
   echo "<tr><td width='80%'></td><td><!--new topic and reply--></td></tr>\n</table>\n";
   $data = file_get_contents('topics/g' . $g . 's' . $s . 't' . $t . '.txt');
   $post = explode("<!--p-->", $data);
   $length = count($post);
   tablestart('1');
   for($z = '0'; $z < $length; $z ++)
    {
     $i = '0';
     $cont = explode("<!--e-->", $post[$pos]);
     echo "<tr><td><b>" . $cont[$i] . "</b><br /><!--future additions--></td><td>\n<table width='100%' style='font-size: xx-small'>\n<tr><td height='3' width='75%'>";
     $i ++;
     echo "Posted on" . $cont[$i] . "</td><td height='3' width='25%'><!--future additions--></td></tr><tr><td width='100%'>";
     $i ++;
     echo $cont[$i] . "</td></tr></table></td></tr>\n";
    }
   echo "</table>\n";
  }
?>

 

which now brings up

 

MySQL error: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'group' at line 1

 

which points me to either the class file or the database itself...the class file doesn't have the word 'group' anywhere in it, so it has to be something with the database...looking at that I find a spelling error in the table name...correcting the error doesn't clear the error...I use phpmyadmin for everything related to the database itself, so I'm not sure what the error is pointing at.

Link to comment
Share on other sites

Yay, you have now fixed the first error :)

 

Previously the error was that $db was not available inside contents().  But now $db is available, and you are getting a new error from a query going through $db.

 

"group" appears in list.php as an argument to contents().  The problem is that "group" is a reserved word for MySQL.  If you really are using "group" as a table name, you will need to put it in backticks I believe.  So your query should be:

 

   $db->query("SELECT * FROM `$table`");

 

I'm not a regular MySQL user so I could be wrong there.  If that doesn't work, try this:

 

   $db->query("SELECT * FROM \"$table\"");

Link to comment
Share on other sites

Maybe there is a server setting that has an unforseen effect.

 

Unfortunately, now that that part is fixed, I'm having issues with my login system that I didn't have without using a class for database connection.  I'm sure it's just a simple thing though, probably didn't properly set up the username and password comparison (again, heh).

Link to comment
Share on other sites

This thread is more than a year old. Please don't revive it unless you have something important to add.

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...

Important Information

We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue.