【问题标题】:Database and OOP Practices in PHPPHP 中的数据库和 OOP 实践
【发布时间】:2010-12-15 13:22:13
【问题描述】:

这种情况很难解释,但请看例子。

我编写了一个加载页面的网站,我初始化了一个数据库类。我将这个类作为函数参数发送给任何需要访问数据库的函数。

我知道这是不好的方法,但目前我不知道如何以其他方式做到这一点。你能帮帮我吗?

例子

class sms {

    function log_sms($message, $db) {

        $sql = "INSERT INTO `smslog` SET
            `mesasge` = '$message'
            ";
        $db->query($sql);

        if ($db->result)
            return true;
        return false;
    }

}

然后在主页上..

$db = new db(username,pass,localhost,dbname);

$sms = new sms;

$sms->log_sms($message, $db);

还有比这更好的方法吗?

【问题讨论】:

    标签: php database oop


    【解决方案1】:

    单例也是应用程序设计的好习惯。它们对于避免在一次调用期间重复查询或计算非常有用。 将 Database 对象传递给每个方法或构造函数不是一个好主意,请改用 Singleton。

    扩展您的数据库,或在您的 db 类中插入静态方法。 (我也会在 db 构造方法中调用配置)

    class database extends db
    {
        public static function instance()
        {
            static $object;
    
            if(!isset($object))
            {
                global $config;
    
                $object = new db($config['username'],$config['pass'],$config['localhost'],['dbname']);
            }
    
            return $object;
        }
    }
    

    让你的方法静态

    class sms {
    
        public static function log($message) {
    
            $sql = "INSERT INTO `smslog` SET `mesasge` = '$message'";
    
            database::instance()->query($sql);
    
            return (bool) database::instance()->result;
        }
    }
    

    下次您需要记录短信时,只需像这样进行静态调用

    sms::log($message);
    

    【讨论】:

      【解决方案2】:

      解决依赖问题的方法有很多(对象A需要对象B):

      构造函数注入

        class Sms { 
              function __construct($db) ....
        }
      
        $sms = new Sms (new MyDbClass);
      

      setter 注入

        class Sms { 
              protected $db;
        }
        $sms = new Sms;
        $sms->db = new MyDbClass;
      

      “注册表”模式

       class Registry {
           static function get_db() {
                return new MyDbClass;
       }}
      
       class Sms {
            function doSomething() {
                $db = Registry::get_db();
                $db->....
        }}
      

      '服务定位器'模式

       class Loader {
           function get_db() {
                return new MyDbClass;
       }}
      
       class Sms {
            function __construct($loader) {
               $this->loader = $loader;
      
            function doSomething() {
                $db = $this->loader->get_db();
                $db->....
        }}
      
        $sms = new Sms(new Loader);
      

      基于容器的自动依赖注入,例如http://www.sitepoint.com/blogs/2009/05/11/bucket-is-a-minimal-dependency-injection-container-for-php

         interface DataSource {...}
         class MyDb implements DataSource {...}
      
          class Sms {
              function __construct(DataSource $ds) ....
      
      
          $di = new Dependecy_Container;
          $di->register('DataSource', 'MyDb');
          $sms = $di->get('Sms');      
      

      仅举几例;)

      我之前给你的福勒的文章也很值得一读

      【讨论】:

      • 你知道每个的处理时间吗?哪个更快,哪个更慢?或者如果没有太大区别,那么构造函数对我来说看起来最简单:)
      • 哦,不错的概述。谢谢:)
      • 你和我对RegistryServiceLocator 模式的理解不同。对我来说,您的注册表看起来像一个 ServiceLocator(一个知道如何实例化对象的注册表),而您的 ServiceLocator 看起来很好......一个通过组合实现到另一个类中的 ServiceLocator。这里没有任何东西看起来像注册表。
      【解决方案3】:

      您可以有一个静态类,它有两个列表,一个是可用连接,另一个是分发连接,并且只有一个连接池。

      或者,如果您使用的是具有快速连接时间的东西,例如 MySQL,那么只需在您的数据库类中创建连接,执行该功能所需的所有查询,然后关闭它。这是我的首选方法。

      【讨论】:

      • 我只使用 1 个连接来节省资源,因为该网站位于共享服务器上,哈哈
      • 那为什么不把查询排队,处理它们,然后在回调中传递结果,打包,否则当两个线程尝试使用同一个连接时,你会遇到问题。
      • 我不能,因为我为每个函数编写了一个类,例如一个用于验证用户的类,一个用于获取用户详细信息的类,一个用于读取用户收件箱等的类,并且他们使用 main $db 类。它在索引文件的顶部进行初始化,并且方法一个接一个地处理每个方法都有查询以仅提取所需的东西并返回一个数组。 HTML 像 MVC 一样在模板页面上呈现。所以第二个查询仅在第一个查询之后执行。但是我讨厌在每个函数上添加 $db 并且我知道它是否会使事情变慢
      • 您应该将这些陈述添加到您的问题中,这将有助于确保您获得最佳答案。
      【解决方案4】:

      对于初学者,您可以在每个需要使用数据库的类中创建一个受保护的 $db 变量。然后,您可以将 $db 传递给类构造函数。这是更新的代码:

      $db = new db(username,pass,localhost,dbname);
      $sms = new sms($db);
      $sms->log_sms($message);
      
      class sms {
      
          protected $db;
      
          public function __construct($db) {
              $this->db = $db;
          }
      
          public function log_sms($message) {
              $sql = "INSERT INTO `smslog` SET
                      `mesasge` = '$message'
                      ";
              $this->db->query($sql);
      
              if ($this->db->result)
                      return true;
              return false;
          }
      }
      

      这个例子在 PHP 5 中。

      【讨论】:

      • 这是最好的方法吗?我有将近 14 个类,所以我应该为每个类添加一个构造函数吗? P.S 这是一个社交网站
      • 没有最好的办法。 cballou 给出的方法当然是一个好方法。为了知道这是否对您的 14 个班级来说是一个好方法,我们需要知道它们是什么。在任何情况下,如果你在这 14 个类上有方法,比如 log($msg, $db),你需要传递 $db 对象的次数(可能甚至更多),而不是作为构造函数传递它时所需要的次数(甚至更多)论据。
      • 是的 14 个类我的意思是我还有 14 个类需要使用 DB 类(如个人资料、用户设置、专辑、视频、身份验证、消息、网络、推荐、更新等),是的我在每个方法的参数中都提供了 db。我使用 $db 作为我相信的大约 50 种或更多此类方法的参数。如果有更好的方法,我不介意更改完整的代码,因为网站还有很多东西要添加。
      • 如果有任何改进的迹象,这会将作为参数传递的 $db 从 50 减少到 14。 @stereo 的解决方案是那些了解正确 OOP 和模式的人的必经之路。如果您必须返回并添加新的数据库抽象层(即缓存、另一个数据库等),这将是未来最易于维护的。
      猜你喜欢
      • 2016-08-04
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-08-04
      • 2011-02-03
      • 2014-01-11
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多