2013-12-11 18:17 阅读 31


In PHP, I have two classes: Database and Item.

Database contains the connection properties and methods. For example, Database::Query can be used to pass a query string, etc.

Item is a generic item identifier. It's built by passing it an itemID which is then used to query the database for the rest of the item information.

In this case, what's the best practice for creating Item objects if they require database access? Is it normal to create each one using this syntax:

$item = new Item(12345, $db);

Or is it better, acceptible, or possible to create the Database object and have it used for each Item created in the application, such that the call could become:

$item = new Item(12345);

The second seems a lot cleaner (and can be expanded so that similar types of objects don't also need that $db addon), but I'm looking for suggestions from those who have more experience at this than I do! Thanks!

  • 点赞
  • 写回答
  • 关注问题
  • 收藏
  • 复制链接分享

3条回答 默认 最新

  • 已采纳
    doupai6875 doupai6875 2013-12-11 18:46

    I would suggest that most seasoned developers would lean toward the approach of dependency injection as demonstrated in your first example.


    Well largely because this allows you to decouple the class to which the dependency is being injected from the dependency's implementation.

    So consider this dependency injection example:

    Class some_class {
        protected $db;
        __construct($db) {
            if($db instanceof some_db_class === false) {
                throw new Exception('Improper parameter passed.');
            $this->db = $db;

    Here you could pass any type of object so long as it was an instance of some_db_class it could be a subclass of that object that implements the same methods used by this class. That doesn't matter to this class as long as the methods are implemented (you of course could also check that a passed object implements a specific interface in addition to or in lieu of checking its instance type).

    This means that, for example, you can pass a mock DB object for testing or something like that. The class doesn't care as long as the methods are implemented.

    Now consider the singleton approach (or similar instantiation of DB from with the class):

    Class some_class {
        protected $db;
        __construct() {
            $this->db = some_db_class::get_instance();

    Here you have tightly coupled your class to a specific database class. If you wanted to test this class with a mock DB implementation it becomes very painful in that you need to modify the class to do so.

    I won't even get into discussion of using global as that is just poor practice and should not be considered at all.

    点赞 评论 复制链接分享
  • duanbi8529 duanbi8529 2013-12-11 18:24

    Typically a database connection object is global, or accessible globally. That works well for the vast majority of applications.

    I do something like this (simplified for example purposes):

    $db = connect_to_db();
    function GetDB()
       global $db;
       return $db
    //inside the item object
    function Load( $id)
       $db = GetDB();

    There are, of course, cases where this isn't the best route. As always, it depend on the specific needs of your application.

    点赞 评论 复制链接分享
  • dongting3135 dongting3135 2013-12-11 18:34

    I would recommend using the Singleton Pattern for your database connection. This is actually the best practice. As you really dont need to instances of your database connection.

    class Database_Instance
        private static $database;
        public static function getDatabaseObject() {
            if (!self::$db) {
                self::$db = new PDO( );
            return self::$db;
    function callWhatSoEver()
        $connection = Database_Instance::getDatabaseObject();

    For more information about the singleton pattern, see: http://en.wikipedia.org/wiki/Singleton_pattern

    点赞 评论 复制链接分享