如何在OOP中访问数据库类?

时间:2011-08-13 13:55:09

标签: php oop

所以我知道不应该问他们标题中“最好的”问题,但是真的......你应该怎么做?

我们有一个数据库类,例如,一个用户类。用户类将获得诸如create()和update()之类的方法,这些方法需要执行数据库操作。

据我所知,有两个主要选项,在每个__construct()中传递数据库对象或使数据库类静态。

(关于OOP +数据库驱动的网站的任何其他提示也很感激)

5 个答案:

答案 0 :(得分:2)

这里一个非常常见的模式是使数据库类成为单例构造,然后将其传递给每个对象构造函数(称为Dependency Injection)。

使数据库对象成为单例的目的是确保每个页面加载只进行一次连接。如果由于某种原因需要多个连接,您可能希望以不同的方式执行此操作。通过构造函数传递它非常重要,而不是在不相关的类中创建数据库对象,以便您可以更轻松地测试和调试代码。

// Basic singleton pattern for DB class
class DB
{

  // Connection is a static property
  private static $connection;

  // Constructor is a private method so the class can't be directly instantiated with `new`
  private function __construct() {}

  // A private connect() method connects to your database and returns the connection object/resource
  private static function connect() {
    // use PDO, or MySQLi
    $conn = new mysqli(...);
    // Error checking, etc
    return $conn;
  }

  // Static method retrieves existing connection or creates a new one if it doesn't exist
  // via the connect() method
  public static function get_connection() {
    if (!self::$connection) {
      self::$connection = self::connect();
      // This could even call new mysqli() or new PDO() directly and skip the connect() method
      // self::$connection = new mysqli(...);
    }
    return self::$connection;
  }
}

class Other_Class
{

  // accepts a DB in constructor
  public function __construct($database) {
    //stuff
  }
}

// Database is created by calling the static method get_connetion()
$db = DB::get_connection();

$otherclass = new Other_Class($db);

// Later, to retrieve the connection again, if you don't use the variable $db
// calling DB::get_connection() returns the same connection as before since it already exists
$otherclass2 = new Other_Class(DB::get_connection());

另一种方法是创建数据库类直接扩展 mysqliPDO。在这种情况下,__construct()方法将对象提供给getConnect(),如

public static function get_connection() {
  if (!self::$connection) {
    self::$connection = new self(/* params to constructor */);
  }
  return self::$connection;
}

答案 1 :(得分:1)

那么,你可以做的是将数据库访问层放在一个对象中,然后传递给你的对象,尊重控制模式的反转。

如果你想向这个方向挖掘一下,看一下依赖注入(DI):http://en.wikipedia.org/wiki/Dependency_injection

拥有单身通常是一个坏主意,因为在测试代码时最终会遇到问题。

答案 2 :(得分:1)

在诸如User之类的模型类中具有数据库访问逻辑违反了关注点分离原则。通常DAO(数据访问对象)处理与数据库相关的问题。

有一些ORM框架,比如Hibernate,可以很好地处理OO和关系模型之间的不匹配,可能会节省大量的手工工作。

答案 3 :(得分:1)

我真的很惊讶,没有人这么说,但在这里:ORM

如果您选择的武器是PHP,那么主要选项是PropelDoctrine。他们都有很多优点和缺点,但毫无疑问他们是强大的。举个例子,来自Propel(我个人最喜欢的)用户手册:

// retrieve a record from a database
$book = BookQuery::create()->findPK(123); 

// modify. Don't worry about escaping
$book->setName('Don\'t be Hax0red!'); 

// persist the modification to the database
$book->save();

$books = BookQuery::create()  // retrieve all books...
  ->filterByPublishYear(2009) // ... published in 2009
  ->orderByTitle()            // ... ordered by title
  ->joinWith('Book.Author')   // ... with their author
  ->find();
foreach($books as $book) {
  echo  $book->getAuthor()->getFullName();
}

你不会得到比这更多的OO!

他们会为你处理很多事情,从数据库供应商那里抽象你的数据。也就是说,您应该能够(相对轻松地)从MySQL移动到SQL Server,如果您正在为Web应用程序构建自己的工具,那么能够适应不同环境是一件非常重要的事情。

希望我能帮忙!

答案 4 :(得分:0)

嘿,看看ORM吧。让他们为你努力工作?流利的nhibernate或microsofts实体框架。

我可能会误解你的问题。对不起,如果是这样