views:

87

answers:

5

What I want to do is access the query function in my database class form anther class. Evey time a query is done I track the time it takes and add the the query count, I want to do that for all query's.

The layout I have now is:

                Global
     -----------------------------
     |                           |
database class          application class
                                 |
                           program class

When the database class starts it connect to the database and does some query's. The next time its needed is in the program class.

I need to keep the querycount and totaltime variables and add to them. I also would like a simple function call, I don't want to start the class for each program. It seams like there should be a way to call it at the application class level and be able to use the query function at the program level and to the connect and close at the global level.

I hope this makes sense, I know what I want but I have problems putting it into words...

A: 

PHP's static keyword is what you need to look at.

http://php.net/manual/en/language.oop5.static.php

Beware though, if lots of classes are calling your static methods you may need to think about threading issues.

Paolo
+1  A: 

I'm not sure if I understood your problem correctly but I'd suggest that you introduce static variables into your database class that are then used to store the data that you want the class to "remember". Like this:

class Database
{
public static $queryCount = 0;
public static $queryDuration = 0;

/*
  ... the rest of your database stuff
*/
}

These two variables are accessible via Database::$queryCount and Database::$queryDuration and will keep their values in the class and not the instantiated objects.

Inside your query methods you can update their values like:

Database::$queryCount++;

and at the end of your script, you can read their contents.

Techpriester
As far as I can see, it doesn't make sense to declare them as `public` though, since they should only be updated when something like `query()` is called - inside the class.
Franz
Right, a cleaner approach would be to declare them private or protected and access them via appropriate methods from within the class. But I just wanted to show my point here with the least possible amount of code :)
Techpriester
Yeah, I can see that. What I meant, though, is that they shouldn't even be allowed to be set from outside the class.
Franz
I had looked at doing a static variables before but didn't see the that they wound do what I wanted them to. Thanks!
Scott
A: 

One way is to make your classes' functions static which you can use straight away. Other possibility is to extend the class which contains the function you want to call. You can also use call_user_func_array function to call a function from any class.

Anyways this video is the answer to your question i think:

http://www.killerphp.com/videos/calling_functions_from_another_class.php

Sarfraz
A: 

Have a look at Zend_Db_Profiler as it does exactly this. You might get some ideas for your own code from there.

If I had to do this myself, I'd probably write a Profiler Decorator for the database class that collects the query statistics for me, each time a query is run.

Another option would be to have your DB class and Profiler class use a Subject/Observer pattern, where the DB class notifies the profiler each time a query is run.

Or you could simply inject the Profiler instance into the DB class and delegate collection from the DB class to the profiler.

However, I would not solve the collection as such within the DB class with static properties, as this statistic collection is not the concern of the class.

In addition to that, I suggest you defer the actual connect calls to the database to when they are needed. Dont connect when you instantiate the DB class for the first time, but put that code into a connect method. Then when someone calls your query method, check if connect has been called and if not, run connect(). There is no need to do the connection, if nothing gets queried.

Gordon
A: 

I think you could take a look at the Factory pattern (makes creating subclasses for different database types easier, too.

Let me provide a modified version of it below:

class Database
{
    protected static $instance = NULL;

    public static function factory($type = '')
    {
        $type = strtolower($type);

        if (self::$instance == NULL)
        {
            $className = 'Database_'.ucfirst($type);

            // Include the class and do some checks here

            self::$instance = new $className;
        }

        return self::$instance;
    }

You can create your database wherever you create it with this piece of code:

$db = Database::factory('mysql');

After that, you can access your database object globally like this:

$db = Database::factory();

Your subclasses have to be stored in classes named like Database_Mysql or Database_Postgresql.

Franz