Page 1 of 1

Calling a class within another class?

Posted: Thu Sep 04, 2008 10:09 am
by ayfine
I am currently working on a CMS, and I was using and calling other classes from within others before I realized that this would not work. I do not really want to recode all of my backend, is there an easy way around this?

For example, I made a class with all of my basic mysql functions.

Code: Select all

class sql {
    function select($table, $where1, $where2) {
        if(is_null($where1) or is_null($where2)) {
            $sql = mysql_query("SELECT * from $table") or die(mysql_error());
        }
        else {
            $sql = mysql_query("SELECT * from $table where '$where1' = '$where2'") or die(mysql_error());
        }
    }
    function select_order($table, $where1, $where2, $order, $by) {
        if(is_null($where1) or is_null($where2)) {
            $sql = mysql_query("SELECT * from $table") or die(mysql_error());
        }
        else {
        $sql = mysql_query("SELECT * from $table where '$where1' = '$where2' order by $order $by") or die(mysql_error());
        }
    }
    function tracker($function) {
        $ip = getenv('REMOTE_ADDR');
        $date = date("F j, Y, g:i a");
        $track = mysql_query("INSERT into log (id, ip, date, user, function) values ('', '$ip', '$date', '{$_SESSION['uid']}', '$function')") or die(mysql_error());
    }
}
 
and I call it later in a different class

Code: Select all

class user {
    function login($email, $pass) {
        $sql->select("users", "email", "$email");
        if(mysql_num_rows($sql) == "0") {
            $error->nouser();
        }
        $a = mysql_fetch_array($sql);
        if($a['pass'] == md5($pass)) {
            $_SESSION['uid'] = $a['id'];
            $_SESSION['name'] = $a['name'];
            $_SESSION['group'] = $a['group'];
            $this->tracker("login");
        }
        else {
            $error->wrongpass();
        }
    }
    function register($name, $pass, $email) {
        $sql->select("users", "name", "$name");
        if(mysql_num_rows($sql) != "0") {
            $error->nameinuse();
        }
        $check = mysql_query("SELECT * from users where 'email' = '$email'") or die(mysql_error());
        if(mysql_num_rows($check) != "0") {
            $error->emailinuse();
        }
        $passw = md5($pass);
            // validation key creation
            $a = date(U);
            $b = str_rot13($a);
            $c = "$name $b";
            $key = md5($c);
        $register = mysql_query("Insert into users (name, email, password, group, key) values ('$name', '$email', '$passw', '0', '$key')") or die(mysql_error());
        $message = "Thank you for registering on the Clayton High School Globe website. To activate your account and comment on stories, you must validate your account. \n To do so, click <a href='http://chsglobe.com/validate/$key'>here</a>. \n AOL users may need to copy and paste http://chsglobe.com/validate/$key into their browser. \n - Clayton Globe Staff";
        mail($email, "Clayton Globe Account Validation", $message);
        $sql->tracker("register");
    }
    function validate($key) {
        $this->select("users", "key", "$key");
        if(mysql_num_rows($sql) == "0") {
            $error->invalidkey();
        }
        $a = mysql_fetch_array($sql);
        $update = mysql_query("UPDATE users set group='1' where id='{$a['id']}'") or die(mysql_error());
        $sq;->tracker("validate");
    }
    function changepass($old, $new) {
        $md5 = md5($old);
        $sql->select("users", "id", "{$_SESSION['uid']}");
        $a = mysql_fetch_array($sql);
        if($a['pass'] != $md5) {
            $error->wrongpass();
        }
        $new5 = md5($new);
        $update = mysql_query("UPDATE users set pass='$new5' where id='{$_SESSION['uid']}'") or die(mysql_error());
        $sql->tracker("changepass");
    }
    function logout() {
        $sql->tracker("logout");
        session_destroy();
        unset($_SESSION['uid'], $_SESSION['name'], $_SESSION['group']);
    }
}
Is there a way around this or am I going to have to recode each time I call a separate class?

In case it is needed I get this error - Fatal error: Call to a member function select() on a non-object in /home/assman/public_html/alexanderfine/globe/backend.php on line 66

Re: Calling a class within another class?

Posted: Thu Sep 04, 2008 10:26 am
by andyhoneycutt
For starters you're using the sql class in the way you would an instantiated object. You don't need to do this because your sql class appears to function as a static class (basically a library of functions). You'll want to modify the way you are calling your sql class:

Code: Select all

function login($email, $pass) {
        $result = sql::select("users", "email", "$email");
        if(mysql_num_rows($result) == "0") {
            $error->nouser();
        }
You will also want your sql::select() function returning a result value:

Code: Select all

function select($table, $where1, $where2) {
        $sql = 0;
        if(is_null($where1) or is_null($where2)) {
            $sql = mysql_query("SELECT * from $table") or die(mysql_error());
        }
        else {
            $sql = mysql_query("SELECT * from $table where '$where1' = '$where2'") or die(mysql_error());
        }
        return $sql;
    }
Alternately you could build a dynamic class that keeps the results to itself, but your sql class should do fine almost as-is as a static class.

-Andy

Re: Calling a class within another class?

Posted: Thu Sep 04, 2008 2:37 pm
by ayfine
I switched all of my coding to that, and it seems as though the sql is never executed. The register script is supposed to check if a username already exists in the table, and after registering one username someone is allowed to register another one.

Am I doing something wrong?

Re: Calling a class within another class?

Posted: Thu Sep 04, 2008 2:42 pm
by andyhoneycutt
Post your new code, or throw some debugging stuff in there to see if it's actually executing your sql code.

-Andy

Re: Calling a class within another class?

Posted: Thu Sep 04, 2008 3:13 pm
by Christopher
You problem is not classes/objects, it is simply scoping. Where is the $sql variable assigned an object? It is not passed to these methods. That is the first thing to do.

Re: Calling a class within another class?

Posted: Thu Sep 04, 2008 7:27 pm
by andyhoneycutt
arborint wrote:You problem is not classes/objects, it is simply scoping. Where is the $sql variable assigned an object? It is not passed to these methods. That is the first thing to do.
This error: "Fatal error: Call to a member function select() on a non-object" explicitly denotes a problem with a class/object (or lack thereof). The only problem with this code is that the object being called is being called improperly as an instance (maybe this is the scope you're talking about) and that the class (which is written as though it is static) returns no values.

Re: Calling a class within another class?

Posted: Thu Sep 04, 2008 10:16 pm
by ayfine
Thank you all for your very fast responses and helping me so far.
andyhoneycutt wrote:Post your new code, or throw some debugging stuff in there to see if it's actually executing your sql code.

-Andy
I was not getting any errors at first, but I figured that the query wasn't be executed because if it was, it would have died. I also decided to make it display the number of rows, which output 0, which is completely wrong.

Here's the snippet of the register function, which is in a class called user.

Code: Select all

    function register($name, $pass, $email) {
        $result = sql::select("users", "name", "$name");
            if(mysql_num_rows($result) != 0) {
                $msg = error::nameinuse();
                die($msg);
            }
        $result2 = sql::select("users", "email", "$email");
            if(mysql_num_rows($result2) != 0) {
                $msg = error::emailinuse();
                die($msg);
            }
        $passw = md5($pass);
            // validation key creation
            $a = date(U);
            $b = str_rot13($a);
            $c = "$name $b";
            $key = md5($c);
        $register = mysql_query("Insert into users (name, email, password, type, verify) values ('$name', '$email', '$passw', '0', '$key')") or die(mysql_error());
}
 
The sql function which is called is located in a separate class called sql

Code: Select all

    function select($table, $where1, $where2) {
        $sql = 0;
            if(is_null($where1) or is_null($where2)) {
                $sql = mysql_query("SELECT * from $table") or die(mysql_error());
            }
            else {
                $sql = mysql_query("SELECT * from $table where '$where1' = '$where2'") or die(mysql_error());
            }
        return $sql;
    }
Although I do not get any errors, what I want it to do is obviously not working.

Also could someone please explain to me what scoping is? I am new to OOP programming in php, and I have never really done anything past classes holding functions as a way of organizing them. (I sort of regret trying to use classes for all this.. I think it could have been accomplished easier with just plain functions)

If needed: I don't have $sql = new sql until the very end of my classes file.

Re: Calling a class within another class?

Posted: Thu Sep 04, 2008 11:05 pm
by pcoder
Can't you extend the Sql class from User class.
Then you can easily call the public or protected function of Sql class from User class.
I mean

Code: Select all

 
class User extends Sql{
  
}
 
If you are doing OOP, please be sure the scope of variable and function.

Re: Calling a class within another class?

Posted: Thu Sep 04, 2008 11:20 pm
by ayfine
pcoder wrote:Can't you extend the Sql class from User class.
Then you can easily call the public or protected function of Sql class from User class.
I mean

Code: Select all

 
class User extends Sql{
  
}
 
If you are doing OOP, please be sure the scope of variable and function.
I haven't been extending the classes. Should I just make all classes extend my sql class?

Re: Calling a class within another class?

Posted: Thu Sep 04, 2008 11:32 pm
by pcoder
It depends upon your class structure.
If you do not need to extend it, then you can call it like this.

Code: Select all

 
require('Sql.php');
class User{
public function __construct(){
  Sql::function();
}
}
 

Re: Calling a class within another class?

Posted: Thu Sep 04, 2008 11:44 pm
by pcoder
And one thing i should have to remember you, only if you are not aware.
Just be confident with PPP visibility rules. :)

Re: Calling a class within another class?

Posted: Fri Sep 05, 2008 12:45 am
by andyhoneycutt
Your code appears solid to me at first glance. Although I could be wrong, I strongly suspect that your query is actually returning zero results. One way to test this is to echo the query (for the users where email = $email) and paste it into your mysql console- be it phpMySqlAdmin, or an actual console, and see if it returns any results. I suspect it won't.

As far as scope goes, you may need to first learn what scope means. Essentially the scope of an item refers to it's place in a hierarchy. Consider the concepts of local and global. A local item is only available to it's peers. A global item is available to all other items. The scope of an item defines it's accessibility to other items. Essentially, the higher the scope (something defined outside a code block, and all subsequent code blocks), the more availability it will have to subsequent code blocks. Consider:

Code: Select all

$variable_1 = "highest scope";
// deeper code block:
if( 1 )
{
  $variable_2 = $variable_1;
  // $variable_2 is now set to the value "highest scope"
  // deeper code block:
  if( 1 )
  { 
    $variable_3 = $variable_2;
    // $variable_3 is now set to the value "highest scope"
  }
}
$variable_4 = $variable_2;
// technically, $variable_2 is outside the scope: it's nested deeper
// than what we're currently executing. you will find in php scope seems
// to be an archaic concept...
//
// $variable_4 technically should equal null
$variable_5 = $variable_1;
// $variable_5 is now set to the value "highest scope", as per
// the value of $variable_1 which is in a higher, or equal scope.
I hope this makes sense, feel free to ponder the idea and pose some questions...

-Andy