Page 1 of 1

Communicating Between Classes

Posted: Thu Mar 13, 2008 11:10 pm
by ird
Hi. I'm currently writing a small CMS (sort of) for personal use.

I'm trying to write it with OOP but it's been nothing but headaches. I'm trying to do a few things and I can't find much info on how to do them.

A) A global class that deals with the database (the connection, queries, etc)
B) Another global class that deals with errors (Handles them, log, etc)
C) Use methods from one object in another object (IE use the database object in another class like "user" to get a users information).

Is there any way to use the database object (And an error handling object that I haven't wrote yet) without passing them to every object I want to use them in.

Here is my working code. If anyone can point me towards a more elegant way to do this, I would appreciate it.

Code: Select all

<?php
require_once('tiff_func.php');
 
class database
{
    private static $db_handle;
 
    function __construct()
    {
        require_once('config/db_conf.php');
        $this->db_handle = mysql_connect(MYSQL_HOST, MYSQL_USER, MYSQL_PASS)
            or exit(mysql_error());
        mysql_select_db(MYSQL_DB)
            or exit(mysql_error());
    }
    function query($sql)
    {
        $sql = mysql_real_escape_string($sql);
 
        echo $sql; //debug purposes.
 
        if (empty($sql))
        {
            return NULL; //NO query given.
        }
        else
        {
            $results = mysql_query($sql);
        }
 
        if ($results === TRUE)
        {
            return 1;
        }
        if ($results === FALSE)
        {
            return 0;
        }
 
        if (mysql_num_rows($results) == 1 && mysql_num_fields($results) == 1)
        {
            $results = mysql_fetch_row($results);
            return $results[0];
        }
        while ($tmp = mysql_fetch_assoc($results))
        {
            $resultArr[] = $tmp;
        }
        if (is_array($resultArr[0]) && count($resultArr) == 1)
        {
            return $resultArr[0];
        }
        return $resultArr;
    }
    function result_count($table, $row = NULL, $match1 = NULL, $match2 = NULL)
    {
        if (empty($row))
        {
            $row = '*';
        }
        $sql = "SELECT count($row) FROM $table";
        if (!empty($match1) && empty($match2))
        {
            $sql .= " WHERE $row = '$match1'";
        }
        if (!emptyEx($match1, $match2))
        {
            $sql .= " WHERE $match1 = '$match2'";
        }
        $results = $this->query($sql);
        return $results;
    }
    function __destruct()
    {
        mysql_close($this->db_handle);
    }
}
$db_handle = new database();
 
class input_validator {
    function user_name($user_name) {
        $pattern = "/^[a-zA-Z0-9]*$/";
        $user_name = htmlspecialchars($user_name);
        if (!preg_match($pattern, $user_name))
        {
            //ERROR
            return 0;
        }
        return 1;
    }
}
$input_validator = new input_validator();
 
class user {
    public $current_user;
 
    function __construct($db_handle)
    {
        $this->db_handle = $db_handle;
    }
    function return_all_users()
    {
        $users = $this->db_handle->query("SELECT * FROM userinfo");
        if(empty($users))
        {
            $users = "No users";
        }
        return $users;
    }
}
$user_handle = new user($db_handle);
 
//print all the users in the database.
$users = $user_handle->return_all_users();
print_r($users);
 
 
//check to see if a username is valid (in this case, only alpha numeric)
$user_names = array("ryan", "ry@n");
 
foreach ($user_names as $cur_name)
{
     echo "$cur_name is ";
     if ($input_validator->user_name($cur_name))
     {
          echo "Valid Username <br />";
     }
     else
     {
         echo "Invalid Username <br />";
     }
}
?>
 
And 'tiff_func.php' just contains this function.

Code: Select all

function emptyEx()
{
    if (!(func_num_args() > 0))
    {
        return NULL;
    }
 
    $args = func_get_args();
    
    foreach ($args as $tmp)
    {
        if (empty($tmp)) 
        {
            return 1;
        }
    }
    return 0;
}

Re: Communicating Between Classes

Posted: Fri Mar 14, 2008 12:16 am
by Christopher
Using a Registry is an often used solution. However I wonder if you actually have a problem. You say that you have to pass the database class to "every object", but are there really that many objects that need it? Your code only has one. Are you solving a problem that hasn't occured yet?

Re: Communicating Between Classes

Posted: Mon Mar 17, 2008 12:39 am
by ird
I can't seem to find much on a 'registry' with google.

Where can I get more information on implementing one?

Re: Communicating Between Classes

Posted: Mon Mar 17, 2008 1:51 am
by Christopher
search for "registry pattern" or even "registry pattern php"

Re: Communicating Between Classes

Posted: Mon Mar 17, 2008 8:11 am
by Zoxive
patternsforphp has some examples as well as many others.

I belive it also was started by someone from here.

http://www.patternsforphp.com/wiki/Registry

Re: Communicating Between Classes

Posted: Mon Mar 17, 2008 7:00 pm
by ird
Ah, thank you very much.

This is exactly the type of pattern I was looking for.

Also, thanks for introducing me to such a great PHP site.

:D

Re: Communicating Between Classes

Posted: Thu Mar 20, 2008 12:20 am
by ird

Code: Select all

<pre>
<?php
require_once('tiff_func.php');
 
class core {
    private $objects = array();
    private static $instance = NULL;
 
    private function __construct()
    {
        //private construct
    }
    private function __clone()
    {
        //no cloning
    }
 
    function get_instance()
    {
        if (is_null(self::$instance))
        {
            self::$instance = new self();
        }
        return self::$instance;
    }
 
    function __get($label)
    {
        if (isset($this->objects[$label]))
        {
            return $this->objects[$label];
        }
        return false;
    }
    function __set($label, $object)
    {
        if (!isset($this->objects[$label]))
        {
            $this->objects[$label] = $object;
        }
    }
    function init_class($class) // Make creating the class and putting it into the 'core' easier.
    {
        $object = new $class;
        $this->$class = $object;
 
        return $object;
    }
}
$core = core::get_instance();
 
class database
{
    private static $db_link;
 
    function __construct()
    {
        require_once('config/db_conf.php');
        $this->db_link = mysql_connect(MYSQL_HOST, MYSQL_USER, MYSQL_PASS)
            or exit(mysql_error());
        mysql_select_db(MYSQL_DB)
            or exit(mysql_error());
    }
    function query($sql)
    {
        $sql = mysql_real_escape_string($sql);
 
        echo $sql;
 
        if (empty($sql))
        {
            return NULL; //NO query given.
        }
        else
        {
            $results = mysql_query($sql);
        }
 
        if ($results === TRUE)
        {
            return 1;
        }
        if ($results === FALSE)
        {
            return 0;
        }
 
        if (mysql_num_rows($results) == 1 && mysql_num_fields($results) == 1)
        {
            $results = mysql_fetch_row($results);
            return $results[0];
        }
        while ($tmp = mysql_fetch_assoc($results))
        {
            $result_arr[] = $tmp;
        }
        if (is_array($resultArr[0]) && count($resultArr) == 1)
        {
            return $result_arr[0];
        }
        return $result_arr;
    }
    function result_count($table, $row = NULL, $match1 = NULL, $match2 = NULL)
    {
        if (empty($row))
        {
            $row = '*';
        }
        $sql = "SELECT count($row) FROM $table";
        if (!empty($match1) && empty($match2))
        {
            $sql .= " WHERE $row = '$match1'";
        }
        if (!empty_ex($match1, $match2))
        {
            $sql .= " WHERE $match1 = '$match2'";
        }
        $results = $this->query($sql);
        return $results;
    }
    function __destruct()
    {
        mysql_close($this->db_link);
    }
}
 
class user_managment {
    //required objects
    public $database;
    public $core;
 
    function __construct()
    {
        $core = core::get_instance();
        $this->database = $core->database;
    }
 
    function return_all_users()
    {
        $users = $this->database->query("SELECT * FROM userinfo");
        if(empty($users))
        {
            $users = "No users";
        }
        return $users;
    }
}
 
//setup classes
$database = $core->init_class('database');
$user_managment = $core->init_class('user_managment');
 
//testing
$users = $user_managment->return_all_users();
 
print_r($users);
 
?>
</pre>
 
How about something like this?

Re: Communicating Between Classes

Posted: Thu Mar 20, 2008 11:16 am
by Mordred
You seriously miss the point of mysql_real_escape_string() and how it should be used.