php - MVC模型应该如何组成?

  显示原文与译文双语对照的内容

我只是掌握了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调用等等,所有的业务逻辑都属于一个模型。

你可以在模型本身中拥有数据访问,但更容易有一个单独的对象执行数据库查询,而不是让它们直接在模型中执行: 在单元测试( 因为在你的模型中注入一个模拟数据库依赖性) 时,这尤其有用:


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中,你很少需要捕捉/重新抛出异常,因为回溯是保留的,尤其是在像你的示例这样的情况下。 只允许抛出异常并在控制器中捕获它。

在我的例子中,我有一个数据库类来处理所有直接数据库交互,比如查询,获取和。 所以如果我必须将数据库从 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);
 }

. . ..
}

我希望这个例子能帮助你创建一个好的结构。

更多oftenly大多数应用程序将数据显示和处理部分,我们只是把所有的字母 MVC

Model( M ) --> 拥有拥有应用程序状态的属性,它不知道任何关于 VC的东西。

View( V ) --> 显示应用程序的格式,并且只知道它的how-to-digest模型,并且不关心 C

Controller( C ) ----> 已经处理了应用程序的一部分,并充当了在M 和V 之间的连接,它依赖于 MV 不同于 MV

两者之间的关注点分离。 将来,任何更改或者增强都可以很容易地添加。

...