简体   繁体   中英

How to access the database class in OOP?

So I know that questions with 'what is the best' in their title aren't supposed to be asked, but really.. how should you do this?

We have a database class and, for example, a user class. A user class will get methods such as create() and update(), which will need to do database stuff.

As far as I know there are 2 main options, passing on the database object in every __construct() or make the database class static.

(Any other tips about OOP + database driven websites are also appreciated)

A very common pattern here is to make the database class a singleton construct, which is then passed to every object constructor (that is called Dependency Injection ).

The purpose of making the database object a singleton is to ensure that only one connection is made per page load. If you need multiple connections for some reason, you would want to do it a different way. It's important to pass it via the constructors though, rather than creating the database object inside an unrelated class so that you can more easily test and debug your code.

// 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());

Another method is to create your database class directly extending either mysqli or PDO . In that case, the __construct() method supplies the object to getConnect() , as in

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

Well, what you can do is to have the database access layer in one object, which is then passed to your objects, respecting the inversion of control pattern.

If you want to dig a bit into this direction, have a look into dependency injection (DI): http://en.wikipedia.org/wiki/Dependency_injection

Having a singleton is usually a bad idea as you will end up having problems when testing your code.

Having the database access logic within a model class such as User violates the separation of concerns principle. Usually DAO (Data Access Object) handles db related concerns.

There are ORM frameworks such as Hibernate, which handle mismatch between OO and relational models quite well, potentially saving a lot of manual work.

I'm really surprised that no one said this, but here it goes: ORM .

If your weapon of choice is PHP, then the major options are Propel and Doctrine . They both have many strengths and some weaknesses, but there's no doubt that they're powerfull. Just an example, from Propel's (my personal favourite) user manual:

// 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();
}

You won't get more OO than that!

They will handle a lot of things for you like for one, abstracting your data from the database vendor. That said, you should be able to move (relatively painlessly) from MySQL to SQL Server and if you're building your own tools for web applications, then beign able to adapt to different environments is a very important thing.

Hope I can help!

Hey have a look at ORM's. Let them do the hard work for you? fluent nhibernate or microsofts entity framework.

I could be misunderstanding your question. Sorry if so

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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