Объект доступа к данным PHP
Я пытаюсь выяснить, правильно ли я использую шаблон DAO и, точнее, насколько абстрактное db-упорство должно быть к тому моменту, когда оно попадает в мои классы-сопоставления. Я использую PDO как объект абстракции доступа к данным, но иногда мне интересно, пытаюсь ли я слишком сильно абстрагировать запросы.
Я только что рассказал, как я абстрагирую выбор запросов, но я написал методы для всех операций CRUD.
class DaoPDO {
function __construct() {
// connection settings
$this->db_host = '';
$this->db_user = '';
$this->db_pass = '';
$this->db_name = '';
}
function __destruct() {
// close connections when the object is destroyed
$this->dbh = null;
}
function db_connect() {
try {
/**
* connects to the database -
* the last line makes a persistent connection, which
* caches the connection instead of closing it
*/
$dbh = new PDO("mysql:host=$this->db_host;dbname=$this->db_name",
$this->db_user, $this->db_pass,
array(PDO::ATTR_PERSISTENT => true));
return $dbh;
} catch (PDOException $e) {
// eventually write this to a file
print "Error!: " . $e->getMessage() . "<br/>";
die();
}
} // end db_connect()'
function select($table, array $columns, array $where = array(1=>1), $select_multiple = false) {
// connect to db
$dbh = $this->db_connect();
$where_columns = array();
$where_values = array();
foreach($where as $col => $val) {
$col = "$col = ?";
array_push($where_columns, $col);
array_push($where_values, $val);
}
// comma separated list
$columns = implode(",", $columns);
// does not currently support 'OR' arguments
$where_columns = implode(' AND ', $where_columns);
$stmt = $dbh->prepare("SELECT $columns
FROM $table
WHERE $where_columns");
$stmt->execute($where_values);
if (!$select_multiple) {
$result = $stmt->fetch(PDO::FETCH_OBJ);
return $result;
} else {
$results = array();
while ($row = $stmt->fetch(PDO::FETCH_OBJ)) {
array_push($results, $row);
}
return $results;
}
} // end select()
} // end class
Итак, мои два вопроса:
-
Является ли это правильным использованием DAO, или я неправильно истолковываю его?
-
Является ли абстрагирование процесса запроса до такой степени ненужным или даже необычным? Иногда я чувствую, что я пытаюсь сделать вещи слишком легкими...
Ответы
Ответ 1
Похоже, что вы строите слой абстракции persistence поверх PDO (который сам по себе является персистентным слоем), а не объектом доступа к данным. Хотя существует множество форм, которые может принимать DAO, цель состоит в том, чтобы отделить вашу бизнес-логику от механизма сохранения.
Business Logic
|
v
Data Access Object
|
v
Persistence Layer
DAO с db_connect
и select
слишком сильно моделируется после слоя сохранения. Простейшая форма общего DAO состоит в том, чтобы обеспечить основные операции CRUD на уровне объекта, не подвергая внутренности механизма персистентности.
interface UserDao
{
/**
* Store the new user and assign a unique auto-generated ID.
*/
function create($user);
/**
* Return the user with the given auto-generated ID.
*/
function findById($id);
/**
* Return the user with the given login ID.
*/
function findByLogin($login);
/**
* Update the user fields.
*/
function update($user);
/**
* Delete the user from the database.
*/
function delete($user);
}
Если ваши бизнес-объекты являются базовыми объектами модели PDO, вы можете вернуть их из DAO. Имейте в виду, что в зависимости от выбранного вами механизма сохранения, это может быть не идеальным. Я не работал с PDO, но предполагаю, что он похож на другие инструменты ORM, которые создают стандартные объекты PHP, не привязывая бизнес-логику к API PDO. Так что вы, наверное, здесь хорошо.
Если вы выполняли персистентность, обратившись непосредственно к библиотеке mysqli
, например, вы захотите скопировать данные в/из наборов результатов в свои собственные объекты модели. Это задача DAO, чтобы не допустить ее из бизнес-логики.
Используя интерфейс для DAO, вы можете реализовать его для разных инфраструктур персистентности: PDO, Doctrine, raw SQL, что угодно. Хотя вы вряд ли переключите методы mid-project, стоимость использования интерфейса незначительна по сравнению с другими его преимуществами, например. используя макет в модульном тестировании.
Ответ 2
- Это необязательно, но это, безусловно, обычная практика. Есть много библиотек, которые абстрагируют waaaaay дальше, чем то, что вы делаете:)