根据我对MVC的理解,逻辑驻留在模型中, Controller 处理协调部分, View 用于数据表示。
下面是从 Controller 中提取的代码。它是用 PHP 框架 codeigniter 编写的。下面发生的情况是,如果图像可用,它将被删除,否则用户将被重定向到删除图像表单。
if($this->records_model->check_img_availability($img_data))
{
//delete if the image is available
$this->records_model->delete_img($img_data);
}
else
{
//redirected to delete image form
$this->session->set_flashdata('errormsg', 'Img is not available');
redirect(base_url() . 'records/deleteimg/');
}
根据上面的 MVC 是错误的,因为逻辑驻留在 Controller 中。它正在检查图像是否可用,具体取决于该图像将被删除或用户重定向。
如何将逻辑插入模型而不是将其保留在 Controller 中?
最佳答案
使用服务层。您 Controller 中现在拥有的逻辑将进入您的一项服务。
服务通常处理大量相关的应用程序逻辑。
例如,如果您的应用程序销售产品,则购物车和客户结账的功能/逻辑必须转移到某个地方。由于功能相似,您可以将所有相关逻辑推送到 Services\Shopping
类中,并且它可以具有如下所示的 API:
interface Shopping {
/**
* @param int $productId
* @param int $quantity
* @return bool
*/
public function addToCart($productId, $quantity);
/**
* @param int $productId
* @return bool
*/
public function removeItem($productId);
/**
* @param int $productId
* @param int $quantity
* @return bool
*/
public function updateQuantity($productId, $quantity);
/**
* Customer checkout.
*
* @param string $firstName
* @param string $lastName
* @param string $emailAddress
* @return bool
*/
public function checkout($firstName, $lastName, $emailAddress, .....etc);
}
您基本上只需将类似的模型层功能分组到服务中,并为服务命名一个好名称,该名称可以广泛地解释它执行的工作/功能类型。
您的 Controller 现在只需从请求中提取数据并将其发送到服务来完成工作。
将商品添加到购物车的一些 Controller 方法:
$productId = (int)$this->request->post('productId');
$quantity = (int)$this->request->post('quantity');
// Now send the data to the shopping service to do the work.
$this->shopping->addToCart($productId, $quantity);
现在您的 Controller 可以变得精简且没有逻辑。如何实现服务取决于您。服务通常可以依赖其他服务来与模型层的不同功能进行交互。
编辑
对于您的场景,我无法为该服务提供一个描述性名称,因为我不知道有关您删除图像的原因、图像与什么相关等的足够信息,因此我将其称为 Services\Image
。对于服务来说,这可能被认为是一个不好的名称,因为它过于具体,但它仅用于演示目的。
class Image extends AbstractService {
/**
* This is assuming you have an ID for a row in the database containing data
* about the image like the path to the image so it can be deleted from the server.
*
* @param int $id
* @return bool
*/
public function delete($id) {
$mapper = $this->mapperFactory->build('Image');
$image = $mapper->fetch($id);
if( $image === null ) {
return $this->fail('Image does not exist.');
}
try {
$mapper->delete($image); // Delete the image row in the database.
unlink( $image->getPath() ); // Delete the image file from the server.
return $this->success('Image deleted successfully.');
}
catch(\RuntimeException $ex) {
return $this->fail('Failed to delete the image.');
}
}
}
success()
和 fail
方法位于父服务中。他们更新模型层的状态并设置一条消息以在需要时向用户显示。方法 failed()
来自父 AbstractService
,如果您在任何子服务中调用 $this->fail()
,该方法将返回 true。
然后在 View 中您可以看到类似的内容:
if( $this->imageService->hasState() ) {
if( $this->imageService->failed() ) {
// If deleting the image failed do whatever you want here.
// Switch templates, redirect or whatever.
}
else {
// The image was deleted successfully so do whatever you want here.
// Again, switch templates, redirect or whatever.
}
// Bind the message to the template.
}
正如你所看到的, View 有大脑并且可以执行逻辑。这是 CI 很糟糕的一个领域。 View 基本上是没有大脑的模板,因此应该在 View 中的逻辑被推送到 Controller 、服务层等中。
基本上 Controller 通过delete($id)
方法与图像服务通信,该方法尝试删除图像并设置模型层的状态,然后 View 与图像对话服务并询问它处于什么样的状态,并根据模型层的状态继续执行它需要执行的任何逻辑。
在我看来,服务通常不应该知道任何响应或如何发送重定向,这是 View 的责任。
Symfony 可能是最好的 PHP 框架,但许多人说它是学习曲线最陡的框架之一。我在文档中写了几页,直到我开始看到我不同意的东西,所以我决定停止探索它。
PHP 的创建者 Rasmus Lerdorf 甚至说自己目前所有的 PHP 框架都很糟糕。
祝你好运。
关于php - 如何将逻辑插入模型而不是将其保留在 Controller 中?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22169667/