Php 从数据库功能中分离代码

Php 从数据库功能中分离代码,php,database,Php,Database,我现在正在开发一个面向对象的PHP网站,并试图确定从系统的其余部分抽象数据库功能的最佳方法。现在,我有一个DB类来管理系统使用的所有连接和查询(它几乎是MDB2的接口)。然而,当使用这个系统时,我意识到我的代码中到处都显示了很多SQL查询字符串。例如,在我的用户类中,我有如下内容: function checkLogin($email,$password,$remember=false){ $password = $this->__encrypt($password); $

我现在正在开发一个面向对象的PHP网站,并试图确定从系统的其余部分抽象数据库功能的最佳方法。现在,我有一个DB类来管理系统使用的所有连接和查询(它几乎是MDB2的接口)。然而,当使用这个系统时,我意识到我的代码中到处都显示了很多SQL查询字符串。例如,在我的用户类中,我有如下内容:

function checkLogin($email,$password,$remember=false){
    $password = $this->__encrypt($password);
    $query = "SELECT uid FROM Users WHERE email=? AND pw=?";

    $result = $this->db->q($query,array($email,$password));

    if(sizeof($result) == 1){
       $row = $result->fetchRow(MDB2_FETCHMODE_ASSOC);
       $uid = $row['uid'];
    }else{
       return false;
    }

    /* Rest of the login script */
}
我想做的是找出减少内联SQL数量的最佳技术。我知道这样做的一种方法是在用户内部为用户使用的每个查询编写函数(如下所示),但这可能会导致相当多的函数

function checkLogin($email,$password,$remember=false){
    $password = $this->__encrypt($password);
    $uid = $this->do_verify_login_query($email,$password);

    /* Rest of the login script */
}

function do_verify_login_query($email,$encpw){
    $query = "SELECT uid FROM Users WHERE email=? AND pw=?";
    $result = $this->$db->q($query,array($email,$encpw));

    if(sizeof($result) == 1){
       $row = $result->fetchRow(MDB2_FETCHMODE_ASSOC);
       return $row['uid'];
    }else{
       return false;
    }
}

所以…我的问题。管理典型数据库应用程序将使用的大量查询的最佳技术是什么?我所描述的方式是处理这种情况的正确方式吗?或者在DB类中注册一个查询列表,并将传递到DB查询函数的唯一ID(如USER_CHECKLOGIN)与每个查询关联,怎么样?此方法也有助于提高安全性,因为它将限制只能运行在此列表中注册的查询,但在编写所有类函数时还要记住一点。想法?

将SQL提取到单独的函数中是一个不错的开始。您还可以做其他一些事情:

  • 为数据库访问代码创建单独的类。这将有助于确保所有PHP文件中都没有分散的SQL函数
  • 从外部文件加载SQL。这完全分离了SQL代码和PHP代码,使两者更易于维护
  • 尽可能使用存储过程。这将从PHP代码中完全删除SQL,并通过降低执行外部SQL的风险来帮助提高数据库安全性

您可能需要研究如何实现。使用这样的设计模式可以在处理表中数据的方式上提供一定的一致性。这类方法可能有一些缺点,主要是某些类型的查询的性能,但可以解决。

另一种选择是使用ORM,对于PHP来说,最强大的是:


两者都允许您使用一组对象访问数据库,为存储和查询数据提供了一个简单的API,都有自己的查询语言,在内部转换为目标DBMS原生SQL,这将通过简单的配置更改简化应用程序从一个RDBMS迁移到另一个RDBMS的过程。我还喜欢这样一个事实,即您可以封装数据模型逻辑以添加验证,例如,仅通过扩展您的模型类。

既然您说您是以OO PHP的形式进行此操作的,那么为什么您首先要将SQL分散在所有方法中?更常见的模式是:

  • 使用ORM并让它处理数据库
  • 为类提供一个或多个“加载”方法,使用单个查询将对象的所有数据拉入内存,并提供一个“保存”方法,使用单个查询更新数据库中的所有内容。所有其他方法只需要在内存中进行操作,数据库交互仅限于load/save方法
  • 第一个选项通常会更健壮,但第二个选项可能会运行得更快,并且与您习惯的做事方式相比,可能会感觉更熟悉,如果其中任何一个是问题的话


    对于您的登录示例,我的方法是通过电子邮件地址加载用户,调用
    $user->check\u password($entered\u password)
    ,如果
    check\u password
    失败,则抛出异常/返回false/无论发生什么。
    check\u password
    和任何登录处理代码都不需要关心数据库,甚至不需要知道用户是从数据库加载的。

    另一种选择是将查询视为数据并存储在数据库中。例如,您可以创建一个存储具有名称的查询的表和另一个存储该查询的参数的表。然后在PHP中创建一个函数,该函数接受查询的名称和参数数组,并执行查询,返回所有结果。您还可以将其他元数据附加到查询中,以限制对某些用户的访问,对结果应用post函数等。

    存储过程不需要内联SQL语句来执行它们,因为它们只存在于数据库中吗?或者我不明白你说的使用存储过程是什么意思吗?MySQL实际上只是添加了存储过程,我读到了语法没有SQL Server中灵活。在我看来,除非您需要编写广泛或复杂的查询,否则存储过程实际上是无用的。您可以通过函数调用调用存储过程,传递名称和查询参数。回复不错,比尔。我喜欢上面列出的所有方法。我认为使用这种模式的一个优点是,您可以使用相同的结构来表示查询,而不必在生成SQL时担心特定于数据库的语法,从而增加了另一层抽象。