Я просто понимаю структуру MVC, и я часто задаюсь вопросом, сколько кода должно идти в модели. Я имею тенденцию иметь класс доступа к данным, который имеет такие методы:
public function CheckUsername($connection, $username) { try { $data = array(); $data['Username'] = $username; //// SQL $sql = "SELECT Username FROM" . $this->usersTableName . " WHERE Username = :Username"; //// Execute statement return $this->ExecuteObject($connection, $sql, $data); } catch(Exception $e) { throw $e; } }
Мои модели обычно представляют собой класс сущностей, который сопоставляется с таблицей базы данных.
Должен ли объект модели иметь все свойства сопоставления базы данных, а также код выше или это нормально, чтобы отделить этот код, который фактически работает в базе данных?
У меня будет четыре слоя?
Все, что является бизнес-логикой, принадлежит модели, будь то запрос к базе данных, расчеты, вызов REST и т. Д.
Вы можете иметь доступ к данным в самой модели, шаблон MVC не ограничивает вас этим. Вы можете сахара покрывать его услугами, картографами, а что нет, но фактическое определение модели – это слой, который обрабатывает бизнес-логику, не более, не что иное. Это может быть класс, функция или полный модуль с gazillion объектами, если это то, что вы хотите.
Всегда проще иметь отдельный объект, который фактически выполняет запросы к базе данных, вместо того, чтобы их непосредственно запускать в модели: это особенно полезно при модульном тестировании (из-за легкости впрыскивания зависимостей базы данных в вашей модели):
class Database { protected $_conn; public function __construct($connection) { $this->_conn = $connection; } public function ExecuteObject($sql, $data) { // stuff } } abstract class Model { protected $_db; public function __construct(Database $db) { $this->_db = $db; } } class User extends Model { public function CheckUsername($username) { // ... $sql = "SELECT Username FROM" . $this->usersTableName . " WHERE ..."; return $this->_db->ExecuteObject($sql, $data); } } $db = new Database($conn); $model = new User($db); $model->CheckUsername('foo');
Кроме того, в PHP вам редко приходится перехватывать / отменять исключения, потому что backtrace сохраняется, особенно в случае, подобном вашему примеру. Просто разрешите исключение и поймайте его в контроллере.
В Web-MVC вы можете делать все, что угодно.
Первоначальная концепция (1) описала модель как бизнес-логику. Он должен представлять состояние приложения и обеспечивать согласованность данных. Этот подход часто описывается как «толстая модель».
Большинство фреймворков PHP следуют более мелкому подходу, где модель представляет собой просто интерфейс базы данных. Но по крайней мере эти модели должны все еще проверять входящие данные и отношения.
В любом случае, вы не очень далеко, если вы отделите SQL-материал или вызовы базы данных на другой уровень. Таким образом, вам нужно только заботиться о реальных данных / поведении, а не о фактическом API хранения. (Однако это необоснованно переусердствовать. Например, вы никогда не сможете заменить бэкэнд базы данных файловым хранилищем, если это не было разработано заранее.)
Чаще всего большинство приложений будут иметь данные, отображать и обрабатывать часть, и мы просто помещаем их в буквы M
, V
и C
Модель ( M
) -> Имеет атрибуты, которые содержат состояние приложения, и он ничего не знает о V
и C
View ( V
) -> Имеет формат отображения для приложения и только знает о том, как его моделировать, и не беспокоится о C
Контроллер ( C
) —-> Имеет часть обработки и действует как проводка между M и V, и это зависит как от M
, V
от M
и V
В целом между ними существует разделение беспокойства. В будущем любые изменения или улучшения могут быть добавлены очень легко.
В моем случае у меня есть класс базы данных, который обрабатывает все прямые взаимодействия с базами данных, такие как запрос, выборка и т. Д. Поэтому, если мне пришлось изменить мою базу данных с MySQL на PostgreSQL, проблем не возникнет. Поэтому добавление дополнительного слоя может быть полезным.
Каждая таблица может иметь свой собственный класс и иметь свои конкретные методы, но для фактического получения данных он позволяет классу базы данных обрабатывать его:
Database.php
class Database { private static $connection; private static $current_query; ... public static function query($sql) { if (!self::$connection){ self::open_connection(); } self::$current_query = $sql; $result = mysql_query($sql,self::$connection); if (!$result){ self::close_connection(); // throw custom error // The query failed for some reason. here is query :: self::$current_query $error = new Error(2,"There is an Error in the query.\n<b>Query:</b>\n{$sql}\n"); $error->handleError(); } return $result; } .... public static function find_by_sql($sql){ if (!is_string($sql)) return false; $result_set = self::query($sql); $obj_arr = array(); while ($row = self::fetch_array($result_set)) { $obj_arr[] = self::instantiate($row); } return $obj_arr; } }
Объект таблицы classL
class DomainPeer extends Database { public static function getDomainInfoList() { $sql = 'SELECT '; $sql .='d.`id`,'; $sql .='d.`name`,'; $sql .='d.`shortName`,'; $sql .='d.`created_at`,'; $sql .='d.`updated_at`,'; $sql .='count(q.id) as queries '; $sql .='FROM `domains` d '; $sql .='LEFT JOIN queries q on q.domainId = d.id '; $sql .='GROUP BY d.id'; return self::find_by_sql($sql); } .... }
Надеюсь, этот пример поможет вам создать хорошую структуру.