我有一个名为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]
答案 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个数据库对象,那么我的应用程序只返回相同的对象和相同的连接。