当前位置:  开发笔记 > 编程语言 > 正文

为什么在MVC中单独使用模型和控制器?

如何解决《为什么在MVC中单独使用模型和控制器?》经验,为你挑选了1个好方法。

我试图了解Phalcon中的MVC模式.

在我当前的应用程序中,每个表只需要一个模板文件.该模板包含datagrid,SELECT语句,表单,​​添加/编辑/删除按钮,搜索框以及与数据库交互所需的所有内容,如连接信息(当然使用包括尽可能多的内容)防止重复的代码).(我编写了自己的复杂框架,它将xml-templates转换为完整的HTML页面,包括所有生成的Javascript代码和CSS,而不需要业务逻辑所需的任何PHP.而不是为数据库中的每个表都有特定的PHP类,我只使用可以执行所有操作的标准操作脚本和数据库类.我试图更多地遵守Web标准,所以我正在研究替代方案.

我尝试了Phalcon的INVO示例,并注意到Companies-page需要一个Companies模型,一个CompaniesController,一个CompaniesForm和4个不同的视图.对我来说,与我的单个文件模板相比,拥有这么多不同的文件太混乱了.

我同意将表示与业务逻辑分开是有道理的,但我不能真正理解为什么模型和控制器需要在不同的类中.这似乎只会让事情变得更复杂.似乎很多人已经无法确定模型中应该包含哪些内容以及控制器中应该包含哪些内容.例如,如果验证需要业务逻辑,有时会将验证放在模型中,否则在控制器中验证,这看起来非常复杂.

我只在一个小团队工作,因此"关注点分离"(除了演示和业务逻辑)对我们来说并不是最重要的事情.

如果我决定使用单独的模型和控制器类,我可以期待哪些问题?

Ultimater.. 5

Phalcon的Phalcon\Mvc\Model类,您的模型应该扩展,旨在提供面向对象的方式与数据库交互.例如,如果您的表格是Shopping_Cart您的名字,那么您可以为您的班级命名ShoppingCart.如果您的表格中包含"id"列,那么您将在班级中定义一个属性public $id;.

尔康也给你喜欢的方法initialize()beforeValidationOnCreate().我承认这些方法在它们的工作方式和运行时以及为什么你想要首先调用它时会非常困惑.

initialize()是非常不言自明的,只要你的课程被启动就会被调用.在这里,您可以执行以下操作:setSource如果您的表的名称与您的类不同,或者调用类似的方法,belongsTohasMany定义其与其他表的关系.

关系是有用的,因为它可以很容易地做一些事情,比如在用户的购物车中搜索产品,然后使用id,你会获得对Accounts表的引用,最后在买家的购物车中获取商品卖家的用户名.

我的意思是,当然,你可以对这种东西进行单独的查询,但是如果你在一开始就定义表关系,为什么不呢?

就为数据库中的每个表定义专用模型而言,您可以定义自己的自定义方法来管理模型.例如,您可能希望public function updateItemsInCart($productId,$quantity)在ShoppingCart类中定义方法.那么这个想法就是当你需要与ShoppingCart进行交互时,你只需调用这个方法,让模型担心业务逻辑.这不是编写一些update也可以工作的复杂查询.

是的,你可以把这种东西放在你的控制器里.但也有一个DRY(不要重复自己)的原则.MVC的目的是分离关注点.那么,如果您不想要专用的模型部分,为什么要首先关注MVC呢?好吧,也许你不需要一个.并非每个应用程序都需要模型.例如,此代码不使用任何:https://github.com/phalcon/blog

就个人而言,在使用Phalcon的模型结构一段时间后,我开始不喜欢他们的1层模型方法.我更倾向于在实体,服务和存储库的方向上使用多层模型.你可以在这里找到这样的代码:https: //github.com/phalcon/mvc/tree/master/multiple-service-layer-model/apps/models 但是由于使用过程,这种情况很快就会变得过度且难以管理很多抽象.两者之间的某种解决方案通常是可行的.

但老实说,使用Phalcon的内置数据库适配器进行查询并没有错.如果您遇到一个非常难以编写的查询,没有人说您的每个模型都需要扩展Phalcon\Mvc\Model.写下这样的东西仍然是完美的逻辑:

$pdo = \Phalcon\DI::getDefault()->getDb()->prepare($sql);
foreach($params as $key => &$val)
{
    $pdo->bindParam($key,$val);
}
$pdo->setFetchMode(PDO::FETCH_OBJ);
$pdo->execute();
$results=$pdo->fetchAll();

模型非常灵活,没有"最佳"的方式来安排它们."无论如何工作"的方法都很好.以及"我希望我的模型能够为每个我可能想要的操作提供方法".

我承认,在INVO和vokuro半功能示例(仅用于演示目的内置),都不捡好的模型设计习惯如此之大.我建议找一个实际上以严肃方式使用的软件,比如论坛的代码:https://github.com/phalcon/forum/tree/master/app/models

Phalcon仍然是一个新的框架,可以在那里找到好的榜样.


正如您所提到的,关于将所有模型放在一个文件中,这非常好.请注意,如前所述,使用setSource内部initialize,您可以使用与他们正在处理的表不同的方式命名您的类.您还可以利用命名空间并使类与表名匹配.您可以更进一步,创建一个类,使用setSource动态创建所有表.假设你想使用Phalcon的数据库适配器.在PDO上编写自己的代码或使用其他框架的数据库适配器没有任何问题.

正如你所说,在一个小团队中,关注点的分离对你来说并不那么重要,所以你可以在没有模型目录的情况下离开.如果有任何帮助,您可以使用我为您的数据库适配器编写的内容:http: //pastie.org/10631358
然后您将在您的app/library目录中删除它.在配置中加载组件,如下所示:

$di->set('easySQL', function(){
    return new EasySQL();
});

然后在您的Basemodel中放置:

public function easyQuery($sql,$params=array())
{
    return $this->di->getEasySQL()->prepare($sql,$params)->execute()->fetchAll();
}

最后,从模型中,您可以做一些简单的事情:

$this->easyQuery($sqlString,array(':id'=>$id));

或者全局定义函数,以便控制器也可以使用它等.


还有其他方法可以做到这一点.希望我的"EasySQL"组件能够让您更接近目标.根据您的需要,也许我的"EasySQL"组件只是漫长的写作方式:

$query = new \Phalcon\Mvc\Model\Query($sql, $di);
$matches=$query->execute($params);

如果没有,也许你正在寻找更多的方向

$matches=MyModel::query()->where(...)->orderBy(...)->limit(...)->execute();

这完全没问题.



1> Ultimater..:

Phalcon的Phalcon\Mvc\Model类,您的模型应该扩展,旨在提供面向对象的方式与数据库交互.例如,如果您的表格是Shopping_Cart您的名字,那么您可以为您的班级命名ShoppingCart.如果您的表格中包含"id"列,那么您将在班级中定义一个属性public $id;.

尔康也给你喜欢的方法initialize()beforeValidationOnCreate().我承认这些方法在它们的工作方式和运行时以及为什么你想要首先调用它时会非常困惑.

initialize()是非常不言自明的,只要你的课程被启动就会被调用.在这里,您可以执行以下操作:setSource如果您的表的名称与您的类不同,或者调用类似的方法,belongsTohasMany定义其与其他表的关系.

关系是有用的,因为它可以很容易地做一些事情,比如在用户的购物车中搜索产品,然后使用id,你会获得对Accounts表的引用,最后在买家的购物车中获取商品卖家的用户名.

我的意思是,当然,你可以对这种东西进行单独的查询,但是如果你在一开始就定义表关系,为什么不呢?

就为数据库中的每个表定义专用模型而言,您可以定义自己的自定义方法来管理模型.例如,您可能希望public function updateItemsInCart($productId,$quantity)在ShoppingCart类中定义方法.那么这个想法就是当你需要与ShoppingCart进行交互时,你只需调用这个方法,让模型担心业务逻辑.这不是编写一些update也可以工作的复杂查询.

是的,你可以把这种东西放在你的控制器里.但也有一个DRY(不要重复自己)的原则.MVC的目的是分离关注点.那么,如果您不想要专用的模型部分,为什么要首先关注MVC呢?好吧,也许你不需要一个.并非每个应用程序都需要模型.例如,此代码不使用任何:https://github.com/phalcon/blog

就个人而言,在使用Phalcon的模型结构一段时间后,我开始不喜欢他们的1层模型方法.我更倾向于在实体,服务和存储库的方向上使用多层模型.你可以在这里找到这样的代码:https: //github.com/phalcon/mvc/tree/master/multiple-service-layer-model/apps/models 但是由于使用过程,这种情况很快就会变得过度且难以管理很多抽象.两者之间的某种解决方案通常是可行的.

但老实说,使用Phalcon的内置数据库适配器进行查询并没有错.如果您遇到一个非常难以编写的查询,没有人说您的每个模型都需要扩展Phalcon\Mvc\Model.写下这样的东西仍然是完美的逻辑:

$pdo = \Phalcon\DI::getDefault()->getDb()->prepare($sql);
foreach($params as $key => &$val)
{
    $pdo->bindParam($key,$val);
}
$pdo->setFetchMode(PDO::FETCH_OBJ);
$pdo->execute();
$results=$pdo->fetchAll();

模型非常灵活,没有"最佳"的方式来安排它们."无论如何工作"的方法都很好.以及"我希望我的模型能够为每个我可能想要的操作提供方法".

我承认,在INVO和vokuro半功能示例(仅用于演示目的内置),都不捡好的模型设计习惯如此之大.我建议找一个实际上以严肃方式使用的软件,比如论坛的代码:https://github.com/phalcon/forum/tree/master/app/models

Phalcon仍然是一个新的框架,可以在那里找到好的榜样.


正如您所提到的,关于将所有模型放在一个文件中,这非常好.请注意,如前所述,使用setSource内部initialize,您可以使用与他们正在处理的表不同的方式命名您的类.您还可以利用命名空间并使类与表名匹配.您可以更进一步,创建一个类,使用setSource动态创建所有表.假设你想使用Phalcon的数据库适配器.在PDO上编写自己的代码或使用其他框架的数据库适配器没有任何问题.

正如你所说,在一个小团队中,关注点的分离对你来说并不那么重要,所以你可以在没有模型目录的情况下离开.如果有任何帮助,您可以使用我为您的数据库适配器编写的内容:http: //pastie.org/10631358
然后您将在您的app/library目录中删除它.在配置中加载组件,如下所示:

$di->set('easySQL', function(){
    return new EasySQL();
});

然后在您的Basemodel中放置:

public function easyQuery($sql,$params=array())
{
    return $this->di->getEasySQL()->prepare($sql,$params)->execute()->fetchAll();
}

最后,从模型中,您可以做一些简单的事情:

$this->easyQuery($sqlString,array(':id'=>$id));

或者全局定义函数,以便控制器也可以使用它等.


还有其他方法可以做到这一点.希望我的"EasySQL"组件能够让您更接近目标.根据您的需要,也许我的"EasySQL"组件只是漫长的写作方式:

$query = new \Phalcon\Mvc\Model\Query($sql, $di);
$matches=$query->execute($params);

如果没有,也许你正在寻找更多的方向

$matches=MyModel::query()->where(...)->orderBy(...)->limit(...)->execute();

这完全没问题.

推荐阅读
夏晶阳--艺术
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有