我只是掌握了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;
}
}
Run Code Online (Sandbox Code Playgroud)
我的模型往往是映射到数据库表的实体类.
模型对象是否应具有所有数据库映射属性以及上面的代码,或者可以将实际上数据库工作的代码分开吗?
我最终会有四层吗?
这个问题在清除我对此事的困惑方面做得非常好,但我很难找到关于服务层的确切限制应该是什么的可靠来源.
对于这个例子,假设我们正在处理书籍,我们希望通过作者获得书籍.本BookDataMapper可以有一个通用的get()接受条件(S),如书的唯一标识符,作者姓名等这个实现是相当微不足道的(逻辑)方法,但如果我们希望有需要更复杂的查询多个条件是什么?
让我们说我们希望得到某位作者在特定出版商下撰写的所有书籍.我们可以扩展BookDataMapper->get()方法来解析多个条件,或者我们可以编写一个新的方法,如BookDataMapper->getByAuthorAndPublisher().
是否最好让服务层直接调用这些[更具体]的方法,或者在调用BookDataMapper->get()多个条件传递的更通用方法之前解析条件?在后一种情况下,服务层将执行更多逻辑"繁重的工作",使数据映射器相当简单.前一个选项会将服务层几乎完全缩减为中间人,将条件逻辑留给数据映射器等方法BookDataMapper->getByAuthorAndPublisher().
让服务层解析条件的一个明显问题是某些域逻辑泄漏出数据映射器.(这在此处的链接问题中进行了解释.但是,如果服务层要处理条件,则逻辑不会使其脱离模型层;控制器将无论如何调用$book_service->getByAuthorAndPublisher().
我已经在Yii框架上开发了一段时间(4个月),到目前为止,我遇到了一些MVC问题,我想与经验丰富的开发人员分享.我将通过列出它们的复杂程度来介绍这些问题.
[等级1] CR(创建更新)表格.首先,我们有很多形式.每个表单本身都是一个模型,因此每个表单都有一些验证规则,一些属性和一些要对属性执行的操作.在很多情况下,这些表单中的每一个都使用单个活动记录对象在数据库中更新和创建记录.
- >因此,在这种复杂程度上,表格必须如此
打开时,
能够以人性化的方式显示db中的db友好数据
能够显示具有活动记录对象属性的所有表单字段.添加,删除,更改db表中的列必须影响表单的显示.
保存时,能够在获取数据之前将人性化数据格式化为数据库友好数据
在验证时,能够执行由活动记录对象强制执行的基本验证,它还必须执行其他验证以满足某些业务规则.
验证失败时,能够回滚对属性所做的更改以及对数据库所做的更改,并向用户显示其最初输入的数据.
[等级2] 扩展CR表格.一种可以同时从不同表执行记录创建/更新的表单.不仅如此,表单是否会创建/更新其中一个记录有时可能取决于其他条件(更多业务规则),因此表单有时可以更新表A,B但不是D的记录,有时更新A处的记录,D但不是B - >所以在这种复杂程度,我们看到一个表格必须:
能够满足[等级1]
能够有条件地创建/更新某些记录,有条件地创建/更新某些记录的某些列.
[等级3] 模型树.在许多方面,表单在应用程序中的作用是允许用户与您的应用程序交互的端口.为了满足请求,该端口将与许多其他对象进行交互,这些对象又与更多对象进行交互.其中一些对象可以看作是模型.Active Record是一个模型,但是Mailer也可以是模型,因此是RobotArm.这些模型彼此使用以满足用户的请求.每个模型都可以执行自己的操作,整个树必须能够回滚在出错或失败的情况下所做的任何更改.
有没有人遇到或能够解决这些问题?
我想出了很多东西,比如在ModelAttribute对象中封装模型属性,以解决它们在客户端,服务器和数据库层中的存在问题.
我还认为我们应该给模型树提供一个Observer来观察并通知观察到的模型在发生错误时回滚更改.但是如果多个观察者可以存在,如果一个节点使用其父节点的观察者但给其子节点另一个观察者,该怎么办呢?
工程师,开发人员,Rails,Yii,Zend,ASP,JavaEE,任何MVC人员,请加入这个讨论,以便科学.
- 更新teresko的回复: ---
@teresko我实际上打算将服务合并到一个工作单元内的执行中,让工作单元不用担心新的/更新/删除.工作单元内的每个对象都将负责其状态,并且需要实现自己的commit()和rollback().一旦发生错误,工作单元将回滚从最新注册对象到最旧注册对象的所有更改,因为我们不仅处理数据库,还可以使用邮件程序,发布者等.否则,树将成功执行,我们从最旧的注册对象调用commit()到最新的注册对象.这样邮件程序可以保存邮件并在提交时发送.
使用数据映射器是一个好主意,但我们仍然必须确保数据库中的列与数据映射器和域对象匹配.此外,扩展CR表单或具有依赖于其他模型的属性的模型必须在验证和数据类型方面匹配它们的属性.那么也许一个属性可以是一个对象并从一个模型运送到另一个模型?属性还可以判断它是否已被修改,应该对其执行什么验证,以及它如何对人类友好,应用程序友好和数据库友好.对数据库模式的任何更新都将影响此属性,从而抛出异常,要求开发人员对系统进行更改以满足此更改.
php ×2
architecture ×1
attributes ×1
datamapper ×1
dependencies ×1
forms ×1
model ×1
oop ×1
tree ×1