在另一个类中使用类时的OOP效率

时间:2013-05-22 11:02:43

标签: php class oop pdo

我有一个名为DB(class.pdo.php)的类,它使用PDO对mysql查询进行所有处理,使用另一个用于管理登录系统的用户类。

我的问题是总是必须在用户的每个公共函数中实例化$ db,所以我可以使用DB。这有效吗?我不应该在用户的__construct()中实例化数据库吗?

这是我的代码

 require_once("../../class.pdo.php");

class user {

private $db = null;

public function __construct(){
    /* Empty? */
}

public function find_by_email($email){
    $db = new db();
    $db->query('SELECT * FROM users WHERE email = :email LIMIT 1');
    $db->bind(':email',$email);
    $result = $db->single();
    return $result;
}

public function create($email,$password,$first_name,$last_name){ 
    $db = new db();
    $db->query("INSERT INTO users(email,password,first_name,last_name,created_at) VALUES (:email,:password,:first_name,:last_name,NOW())");
    $db->bind(':email',$email);
    $db->bind(':password',$password);
    $db->bind(':first_name',$first_name);
    $db->bind(':last_name',$last_name);
    $result = $db->execute();
    return $db->lastInsertId();
}

 [more similar functions ommited]

5 个答案:

答案 0 :(得分:3)

好吧,尽管有一些评论暗示使用Singleton模式,但我完全不同意将其用于此目的。

您的应用程序不会始终仅使用一个连接到一个数据库。

让我告诉你我是怎么做到的:

class DbConnector {
    private $dbh;
    private $dsn;

    public function __construct($dsn) {
        $this->dsn = $dsn;
    }

    private function connect() {
        if($this->dbh === null) {
            $this->dbh = new PDO($this->dsn);
        }
    }

    public function disconnect {
        if($this->dbh !== null) {
            $this->dbh = null;
        }
    }

    public function query($sql) {
        $this->connect();
        //... do the rest
    }

    public function fetchAll($sql) {
        $this->connect();
        //... do the rest
    }

    public function insert($table, $values) {
        $this->connect();
        //... do the rest
    }

    public function update($table, $values, $cond) {
        $this->connect();
        //... do the rest
    }

    public function delete($table, $cond) {
        $this->connect();
        //... do the rest
    }
}

class User {
    private $dbConn;
    public function __construct(DbConnector $dbConn) {
        $this->dbConn = $dbConn;
    }

    public function create($email,$password,$first_name,$last_name){ 
        $this->dbConn->query("INSERT INTO users(email,password,first_name,last_name,created_at VALUES (:email,:password,:first_name,:last_name,NOW())");
        $this->dbConn->bind(':email',$email);
        $this->dbConn->bind(':password',$email);
        $this->dbConn->bind(':first_name',$email);
        $this->dbConn->bind(':last_name',$email);
        $this->dbConn->execute();
        return $this->dbConn->lastInsertId();
    }

    // ...
}

结果:

  • 没有单身人士使用=可测试。
  • 只需在需要时打开与数据库的连接
  • 您的连接是持久的。如果在每种方法中打开和关闭连接,则会失去创建事务的能力。

答案 1 :(得分:2)

如何使用Singleton模式为连接创建一个对象,并在每次需要时使用它,而不是一直创建新对象?

答案 2 :(得分:1)

我会做一些与延迟加载类似的事情:不要在构造函数中启动,除非你确定每次创建一个对象时确实需要连接,但绝对不会在每个方法调用上创建一个新对象。相反,将结果对象保存到对象var中,该对象var在每个方法调用上检查,如果丢失则启动连接。

class user {
  protected $_db = null;
  private function _init_db() { $this->_db = new XXX; }
  public function create( $x, $y, $z ) {
    if ( ! $this->_db ) $this->_init_db();
    # use $this->_db ..
  }
  public function find_by_email( $x, $y, $z ) {
    if ( ! $this->_db ) $this->_init_db();
    # etc
  }
}

这具有避免全局静态(单例......)的优点,并且只在最后一刻创建连接/对象,因此您确定实际需要它并且它不仅仅是无用的连接。

答案 3 :(得分:1)

说到效率,您的代码的主要问题是它为每个被调用的方法建立新连接。这个确实效率低到杀死数据库服务器。而且它与你遇到的其他问题无法比拟。

所以,一般来说,你可以拥有你想要的任何方式 - 或者在每个函数中以某种方式得到db类的实例或者使用类变量 - 但是无论哪种方式都必须在整个应用程序中使用单个PDO实例< /强>

此外,从代码量的角度来看,我发现你的函数效率很低,并且会以这种方式优化它们

public function create($email,$password,$first_name,$last_name){ 
    $sql = "INSERT INTO users(email,password,first_name,last_name,created_at) VALUES (?,?,?,?,NOW())";
    $this->db->query($sql);
    $result = $db->execute(func_get_args());
    return $db->lastInsertId();
}

答案 4 :(得分:0)

从对象的角度来看,我会让数据库在方法中实例化,而不是整个类。

每个方法只应查看所需的变量和数据,以便执行其功能。 例如,createUser()方法需要查看变量或属性,例如$username$usergroupId以及$database等。

但是,您可能有一个名为randomPassword()的函数,它会从数字和字母生成随机密码。

此randomPassword()函数不需要数据库对象,因此,对象范围中已初始化的数据库连接将是浪费。

最好只在需要它的方法中创建新的数据库对象。

此外,在我的应用程序中,每次使用new database时都不会创建新的数据库连接。相反,我选择了一个单独的PDO数据库对象来保持连接活动。

然后我可以静态地调用数据库对象来检索现有连接。因此,如果在运行我的应用程序的过程中我需要有20个数据库对象,那么我的应用程序只返回相同的对象和相同的连接。