我只是掌握了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;
}
}
我的模型往往是映射到数据库表的实体类。
模型对象应该具有所有数据库映射属性以及上面的代码,还是可以将实际上数据库工作的代码分开?
我最终会有四层吗?
答案 0 :(得分:867)
答案 1 :(得分:35)
业务逻辑的所有内容都属于模型,无论是数据库查询,计算,REST调用等。
您可以在模型本身中访问数据,MVC模式不会限制您这样做。您可以使用服务,映射器和其他方法对其进行糖涂层,但模型的实际定义是处理业务逻辑的层,仅此而已。它可以是一个类,一个函数,或一个包含大量对象的完整模块,如果这就是你想要的。
拥有一个实际执行数据库查询的单独对象总是更容易,而不是让它们直接在模型中执行:这在单元测试时会特别派上用场(因为在你的模拟数据库依赖注入中很容易模型):
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中,您很少需要捕获/重新抛出异常,因为保留了回溯,特别是在您的示例中。只是抛出异常并在控制器中捕获它。
答案 2 :(得分:20)
在网络 - “MVC”中,你可以做任何你想做的事。
原始概念 (1) 将模型描述为业务逻辑。它应该代表应用程序状态并强制执行一些数据一致性。这种方法通常被描述为“胖模型”。
大多数PHP框架遵循更浅层的方法,其中模型只是一个数据库接口。但至少这些模型仍应验证传入的数据和关系。
无论哪种方式,如果将SQL内容或数据库调用分成另一层,那么你就不是很远了。这样,您只需关注真实的数据/行为,而不是实际的存储API。 (但是过度使用它是不合理的。如果没有提前设置,你将永远无法用文件存储替换数据库后端。)
答案 3 :(得分:6)
通常,大多数应用程序都有数据,显示和处理部分,我们只是将所有这些应用程序放在M
,V
和C
字母中。
模型(M
) - >具有保存应用状态的属性,并且不了解V
和C
的任何内容。
查看(V
) - >显示应用程序的格式,并且只知道如何在其上消化模型,并且不关心{{1} }。
控制器(C
) ---->处理应用程序的一部分并充当M和V之间的接线,它取决于C
,{{ 1}}与M
和V
不同。
每个人之间总是存在分离关系。 将来可以非常轻松地添加任何更改或增强功能。
答案 4 :(得分:0)
在我的例子中,我有一个数据库类来处理所有直接数据库交互,例如查询,提取等。因此,如果我必须将数据库从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);
}
....
}
我希望这个例子可以帮助你创建一个好的结构。