我有这个PDO数据库类
class clsDatabase{
// db settings
private $host = 'localhost';
private $user = 'test';
private $dbname = 'test';
private $pass = 'test1';
private $dbh;
private $error;
public function __construct(){
// Set DSN
$dsn = 'mysql: host=' . $this->host . ';dbname=' . $this->dbname;
// Set options
$options = array(
PDO::ATTR_PERSISTENT => true,
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
PDO::MYSQL_ATTR_INIT_COMMAND => 'SET NAMES UTF8'
);
// Create a new PDO instanace
try{
$this->dbh = new PDO($dsn, $this->user, $this->pass, $options);
}
// Catch any errors
catch(PDOException $e){
$this->error = $e->getMessage();
echo $this->error;
exit;
}
}
public function query($query){
$this->stmt = $this->dbh->prepare($query);
}
}
我尝试在不同的类中分隔我的代码,例如我有一个连接到clsUserController的clsDBUser。我这样做,所以我知道什么类使用什么数据库代码。我的clsDBUser类看起来像这样
class clsDBUser extends clsDatabase {
// construct
public function __construct() {
parent::__construct();
}
// get users
public function getUsers($users_id){
$query = "
SELECT
email
FROM
users
WHERE
users_id = :users_id
";
$this->query($query);
$this->bind(':users_id', $users_id);
if($row = $this->single()){
$this->close();
return $row;
}
$this->close();
return false;
}
}
我想知道这是否可行,或者我现在正在每个班级创建一个新的数据库连接?因为通常在PHP4中(是的,我知道旧)我无法识别我每次都必须建立新的数据库连接。
我是否需要改进这一点,我该如何改进呢?
答案 0 :(得分:1)
嘿,我会做这样的事情
class DB {
// connectionStuff goes Here
}
class Model {
private $db
public function __construct($db) {
$this->db = $db;
}
}
使用:
$db = new DB("your connection stuff goes here");
$model = new Model($db);
$userModel = new UserModel($db);
$anotherModel = new AnotherModel($db);
答案 1 :(得分:1)
重建:
仅包含连接内容的clsDB类
class clsDB{
// db settings
private $host = 'localhost';
private $user = 'test';
private $dbname = 'test';
private $pass = 'test';
private $dbh;
private $error;
public function __construct(){
// Set DSN
$dsn = 'mysql: host=' . $this->host . ';dbname=' . $this->dbname;
// Set options
$options = array(
PDO::ATTR_PERSISTENT => true,
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
PDO::MYSQL_ATTR_INIT_COMMAND => 'SET NAMES UTF8'
);
// Create a new PDO instanace
try{
$this->dbh = new PDO($dsn, $this->user, $this->pass, $options);
}
// Catch any errors
catch(PDOException $e){
$this->error = $e->getMessage();
echo $this->error;
exit;
}
}
}
clsDBLogin:
class clsDBLogin{
private $db;
public function __construct($db) {
$this->db = $db;
}
}
在index.php中我做:
$clsDB = new clsDB();
$clsDBLogin = new clsDBLogin($clsDB);
在clsDBLogin中我会这样做:
public function validateLogin($email){
$email = str_replace(' ', '', $email);
$email = strtolower($email);
// Check user in db to start verification
$query = '
SELECT
u.*, ui.*
FROM
users as u,
users_info as ui
WHERE
u.users_id = ui.users_id
AND
u.email = :email
';
$this->db->prepare($query);
$this->db->bindValue(':email', $email, PDO::PARAM_STR);
if($this->db->execute()){
if($row = $this->db->fetch(PDO::FETCH_ASSOC)){
return $row;
}
}
}
答案 2 :(得分:0)
你应该采取mr.void答案中显示的道路。简而言之:
所以它应该像
class clsDBLogin
{
public function __construct($db)
{
$this->db = $db;
}
public function validateLogin($email)
{
$email = trim($email);
// Check user in db to start verification
$query = 'SELECT * FROM users u, users_info ui
WHERE u.users_id = ui.users_id AND u.email = ?';
$stmt = $this->db->prepare($query);
$stmt->execute([$email]);
return $stmt->fetch();
}
}
$dsn = 'mysql: host=localhost;dbname=test;charset=utf8';
$options = array(
PDO::ATTR_PERSISTENT => true,
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
);
// Create a new PDO instanace
$pdo = new PDO($dsn, $this->user, $this->pass, $options);
$DBLogin = new clsDBLogin($pdo);
$user = $DBLogin->validateLogin($email);
答案 3 :(得分:0)
这里有三层:
当我们手动执行此操作时...首先,不要相互扩展。通常:永远不要将另一层扩展到另一层。请改用Dependency Injection(DI)。
当您将所有特定信息(依赖项)作为构造函数参数传递时,它是一个非常简单的DI案例。我的类似活动对象的示例Entity
只知道实体应该如何表现(在存储库中的密钥处)。为简单起见,我使用原始SQL。
存储库类:
class Repository {
private $oPDO;
private $tableName;
private $keyFieldName;
public function __construct($oPDO, $tableName, $keyFieldName) {
$this->oPDO = $oPDO;
$this->tableName = $tableName;
$this->keyFieldName = $keyFieldName;
}
public function getPDO() {
return $this->oPDO;
}
public function getTableName() {
return $this->tableName;
}
public function getKeyFieldName() {
return $this->keyFieldName;
}
public function getEntity($id) {
return new Entity($this, $id);
}
public function createEntity() {
return new Entity($this, null);
}
}
实体类:
class Entity implements ArrayAccess {
private $oRepository;
private $id;
private $record = null;
public function __construct($oRepository, $id) {
$this->oRepository = $oRepository;
$this->id = $id;
}
public function load($reload = false) {
if (!$this->record && !$this->id) {
return false;
}
if (!$reload && !is_null($this->record)) {
return true;
}
$quotedTableName = $this->quoteIdentifier($this->oRepository->getTableName());
$quotedKeyFieldName = $this->quoteIdentifier($this->oRepository->getKeyFieldName());
$selectSql = "SELECT * FROM {$quotedTableName} WHERE {$quotedKeyFieldName} = ?";
$oStatement = $this->oRepository->getPDO()->prepare($selectSql);
$this->bindParam($oStatement, 1, $this->id);
$oStatement->execute();
$result = $oStatement->fetch(PDO::FETCH_ASSOC);
if ($result === false || is_null($result)) {
return false;
}
$this->record = $result;
return true;
}
public function save() {
$oPDO = $this->oRepository->getPDO();
$tableName = $this->oRepository->getTableName();
$keyFieldName = $this->oRepository->getKeyFieldName();
$quotedTableName = $this->quoteIdentifier($tableName);
$quotedKeyFieldName = $this->quoteIdentifier($keyFieldName);
if (is_null($this->id)) {
$insertSql = "INSERT INTO {$quotedTableName} (";
$insertSql .= implode(", ", array_map([$this, "quoteIdentifier"], array_keys($this->record)));
$insertSql .= ") VALUES (";
$insertSql .= implode(", ", array_fill(0, count($this->record), "?"));
$insertSql .= ")";
$oStatement = $oPDO->prepare($insertSql);
$p = 1;
foreach ($this->record as $fieldName => $value) {
$this->bindParam($oStatement, $p, $value);
$p++;
}
if ($oStatement->execute()) {
$this->id = $oPDO->lastInsertId();
return true;
} else {
return false;
}
} else {
$updateSql = "UPDATE {$quotedTableName} SET ";
$updateSql .= implode(" = ?, ", array_map([$this, "quoteIdentifier"], array_keys($this->record)));
$updateSql .= " = ? WHERE {$quotedKeyFieldName} = ?";
$oStatement = $oPDO->prepare($updateSql);
$p = 1;
foreach ($this->record as $fieldName => $value) {
$this->bindParam($oStatement, $p, $value);
$p++;
}
$this->bindParam($oStatement, $p, $this->id);
if ($oStatement->execute()) {
if (isset($this->record[$keyFieldName])) {
$this->id = $this->record[$keyFieldName];
}
return true;
} else {
return false;
}
}
}
public function isExisting($reload = false) {
if (!$this->record && !$this->id) {
return false;
}
if (!$reload && !is_null($this->record)) {
return true;
}
$quotedTableName = $this->quoteIdentifier($this->oRepository->getTableName());
$quotedKeyFieldName = $this->quoteIdentifier($this->oRepository->getKeyFieldName());
$selectSql = "SELECT 1 FROM {$quotedTableName} WHERE {$quotedKeyFieldName} = ?";
$oStatement = $this->oRepository->getPDO()->prepare($selectSql);
$oStatement->bindParam(1, $this->id);
$oStatement->execute();
$result = $oStatement->fetch(PDO::FETCH_ASSOC);
if ($result === false || is_null($result)) {
return false;
}
return true;
}
public function getId() {
return $this->id;
}
public function getRecord() {
$this->load();
return $this->record;
}
public function offsetExists($offset) {
$this->load();
return isset($this->record[$offset]);
}
public function offsetGet($offset) {
$this->load();
return $this->record[$offset];
}
public function offsetSet($offset, $value) {
$this->load();
$this->record[$offset] = $value;
}
public function offsetUnset($offset) {
$this->load();
$this->record[$offset] = null;
}
private function quoteIdentifier($name) {
return "`" . str_replace("`", "``", $name) . "`";
}
private function bindParam($oStatement, $key, $value) {
$oStatement->bindParam($key, $value);
}
}
<强>用法:强>
$oRepo = new Repository($oPDO, "user", "user_id");
var_dump($oRepo->getEntity(2345235)->isExisting());
$oSameUser = $oRepo->getEntity(1);
var_dump($oSameUser->isExisting());
var_dump($oSameUser->getRecord());
$oNewUser = $oRepo->createEntity();
$oNewUser["username"] = "smith.john";
$oNewUser["password"] = password_hash("ihatesingletons", PASSWORD_DEFAULT);
$oNewUser["name"] = "John Smith";
$oNewUser->save();
$oNewUser["name"] = "John Jack Smith";
$oNewUser->save();
当然,您可以使用特定行为从MoreConcreteRepository
和Repository
MoreConcreteEntity
扩展Entity
。
答案 4 :(得分:-1)
只是不要从连接类(clsDBUser
)扩展实体(clsDatabase
)。
为clsDatabase
使用单例(或更高级的模式)。
例如:
class clsDatabase {
static private $instance = null;
// some other private fields
private function __construct(/* parameters*/) {
// do it
}
public static function instance() {
if (is_null(self::$instance)) {
self::$instance = new self(/* pass any parameters */);
}
return self::$instance;
}
public function queryRow($query) {
$oStatement = $this->dbh->prepare($query);
// ...
return $row;
}
}
class clsDBUser {
public function getUser($id) {
$query = "...";
return $clsDatabase::instance()->queryRow($query);
}
}