使用Front Controller Pattern和MVC嵌套控制器


Nesting controllers with the Front Controller Pattern and MVC

我正在使用MVC方法(不使用任何框架,纯PHP)用PHP开发web应用程序。正如MVC通常的情况一样,每个请求都到达前端控制器,前端控制器将其路由到相应的控制器,并执行所请求的操作。URL结构如下:

www.site.com/controller/action

比方说,我正在建立一个电子商务网站,它有不同类别的产品。可能的URL可能是:

www.site.com/sofas/overview
www.site.com/video-games/overview

对于第一个URL,加载"sofas"控制器,并执行其overview()方法。这一切都很有效,直到我们不得不将这些产品嵌套在父类别中。我将使用前面的两个URL来演示我的意思:

www.site.com/furniture/sofas/overview
www.site.com/electronics/video-games/overview

现在,"视频游戏"控制器嵌套在"电子"控制器中。然而,对于当前的"加载控制器->执行操作"结构,这将不起作用。

一个可能的解决方案是在父控制器("电子设备")中创建一个方法,在请求未存在的动作("视频游戏")的情况下执行该方法。此方法检查请求的操作是否作为控制器存在。如果是这样,则加载控制器并执行其操作("概述")。

我徒劳地寻找了标准前端控制器模式的这种限制的解决方案,包括在SO上。我认为我对MVC的实现现在是正确的,但前端控制器仍然带来了限制。

我认为,对于每种不同的产品类型,都必须有一个不同的"控制器",这种想法可能会让你遇到问题。

除非你对每种产品类型都有截然不同的看法,否则我认为控制器会链接到一个概念,比如"目录"(或"产品"或你想称之为什么)。例如,您的URL结构可能看起来像

www.site.com/catalog/furniture/sofas/overview
www.site.com/catalog/electronics/video-games/overview

URI的catalog部分确定控制器,并且附加的URI段本质上是传递给控制器的指示请求细节的参数。

这将很好地与OOP继承结构配合使用,因为您可以有一个根"产品"类,然后用家具、电子产品等的子类来扩展该类,这些子类都有自己特定于该类别的属性。你会选择沙发、电子游戏等的进一步细分。

您的控制器所要做的就是评估请求URI,以确定为请求加载哪个类。所以类似于:

// assume URI has been parsed to get value such as "sofas", "video-games", etc. into a variable called $class_to_load
$product = new $class_to_load;
$product->overview();

您混淆了MVC结构和路由问题。

控制器应该是类似于产品控制器或类别控制器的东西。按功能对控制器进行分组。

现在路由处理请求的结构以及在应用程序中发送请求的位置。

您应该有一个路由层,它知道(例如)将/<category>/<subcategory>/<action>发送到具有适当参数(即类别和子类别)的适当控制器(如产品控制器),以便构建响应。

仅将url直接映射到控制器和操作(即强制执行/<controller>/<action>)是构建应用程序架构的一种非常有限的方式。