Calling a class within another class?

PHP programming forum. Ask questions or help people concerning PHP code. Don't understand a function? Need help implementing a class? Don't understand a class? Here is where to ask. Remember to do your homework!

Moderator: General Moderators

Post Reply
ayfine
Forum Newbie
Posts: 22
Joined: Mon Nov 27, 2006 4:52 pm

Calling a class within another class?

Post 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
User avatar
andyhoneycutt
Forum Contributor
Posts: 468
Joined: Wed Aug 27, 2008 10:02 am
Location: Idaho Falls

Re: Calling a class within another class?

Post 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
ayfine
Forum Newbie
Posts: 22
Joined: Mon Nov 27, 2006 4:52 pm

Re: Calling a class within another class?

Post 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?
User avatar
andyhoneycutt
Forum Contributor
Posts: 468
Joined: Wed Aug 27, 2008 10:02 am
Location: Idaho Falls

Re: Calling a class within another class?

Post by andyhoneycutt »

Post your new code, or throw some debugging stuff in there to see if it's actually executing your sql code.

-Andy
User avatar
Christopher
Site Administrator
Posts: 13596
Joined: Wed Aug 25, 2004 7:54 pm
Location: New York, NY, US

Re: Calling a class within another class?

Post 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.
(#10850)
User avatar
andyhoneycutt
Forum Contributor
Posts: 468
Joined: Wed Aug 27, 2008 10:02 am
Location: Idaho Falls

Re: Calling a class within another class?

Post 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.
ayfine
Forum Newbie
Posts: 22
Joined: Mon Nov 27, 2006 4:52 pm

Re: Calling a class within another class?

Post 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.
User avatar
pcoder
Forum Contributor
Posts: 230
Joined: Fri Nov 03, 2006 5:19 am

Re: Calling a class within another class?

Post 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.
ayfine
Forum Newbie
Posts: 22
Joined: Mon Nov 27, 2006 4:52 pm

Re: Calling a class within another class?

Post 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?
User avatar
pcoder
Forum Contributor
Posts: 230
Joined: Fri Nov 03, 2006 5:19 am

Re: Calling a class within another class?

Post 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();
}
}
 
Last edited by pcoder on Fri Sep 05, 2008 1:04 am, edited 1 time in total.
User avatar
pcoder
Forum Contributor
Posts: 230
Joined: Fri Nov 03, 2006 5:19 am

Re: Calling a class within another class?

Post by pcoder »

And one thing i should have to remember you, only if you are not aware.
Just be confident with PPP visibility rules. :)
User avatar
andyhoneycutt
Forum Contributor
Posts: 468
Joined: Wed Aug 27, 2008 10:02 am
Location: Idaho Falls

Re: Calling a class within another class?

Post 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
Post Reply