简体   繁体   English

从其他类访问一个类中的函数

[英]Accessing a function in a class from other classes

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. 我需要保留querycount和totaltime变量并将其添加。 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. 看起来好像应该有一种方法可以在应用程序类级别调用它,并且能够在程序级别使用查询功能,并可以在全局级别使用connect和close。

I hope this makes sense, I know what I want but I have problems putting it into words... 我希望这是有道理的,我知道我想要什么,但是我很难用语言表达出来……

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. 这两个变量可以通过Database :: $ queryCount和Database :: $ queryDuration访问,并将它们的值保留在类中,而不是实例化的对象中。

Inside your query methods you can update their values like: 在查询方法中,您可以更新它们的值,例如:

Database::$queryCount++;

and at the end of your script, you can read their contents. 在脚本末尾,您可以阅读其内容。

PHP's static keyword is what you need to look at. 您需要查看PHP的static关键字。

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

Beware though, if lots of classes are calling your static methods you may need to think about threading issues. 但是请注意,如果许多类正在调用您的静态方法,则可能需要考虑线程问题。

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. 您还可以使用call_user_func_array函数从任何类调用函数。

Anyways this video is the answer to your question i think: 无论如何,这部影片是您的问题的答案,我认为:

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

Have a look at Zend_Db_Profiler as it does exactly this. 看看Zend_Db_Profiler正是这样做的。 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. 如果必须自己执行此操作,则可能要为数据库类编写一个Profiler Decorator,以便每次运行查询时都为我收集查询统计信息。

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. 或者,您可以简单地将Profiler实例注入DB类,并将DB类的集合委托给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. 不过,我也不会解决这个集合作为这样的静态属性DB类中,因为这统计收集不是类的关注。

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. 首次实例化DB类时不要连接,而是将代码放入connect方法中。 Then when someone calls your query method, check if connect has been called and if not, run connect(). 然后,当有人调用您的查询方法时,检查是否已调用connect,如果没有,请运行connect()。 There is no need to do the connection, if nothing gets queried. 如果没有任何查询,则无需进行连接。

I think you could take a look at the Factory pattern (makes creating subclasses for different database types easier, too. 我认为您可以看看Factory模式(也使创建不同数据库类型的子类更加容易。

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 . 您的子类必须存储在名为Database_MysqlDatabase_Postgresql

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM