允许路由器从数据库查找控制器是个好主意吗?

发布于 2024-09-06 14:30:55 字数 858 浏览 4 评论 0原文

在大多数 PHP MVC 设计结构教程中,路由器类用于获取用户输入并查找正确的控制器,以便准确处理该输入。输入通常采用 url 的形式。例如http://example.com/foo/bar/会要求路由器找到名为foo的控制器并触发方法bar。

PHP 还有一个自动包含功能,需要为您的类使用一致的命名系统。例如,如果我想获取 Foo 类的实例,我需要将该文件命名为 Foo.php,并且其中包含一个名为 Foo 的类。

不幸的是,这些机制同时对命名系统提出了相互竞争的要求。该 URL 非常“面向前面”,因此,客户通常需要它来反映特定页面的内容。例如,如果我有一个提供前往某个地点的路线的页面,则客户可能需要此页面位于 http://example.com/venues/directions/。稍后内容可能会发生变化,场地数量会减少到 1 个,现在客户端希望 URL 为 http://example.com/venue/directions/。显然,这是一个非常简单的例子,但我认为偶尔更改 url 的需要是明确的。

由于 url 与控制器类的连接非常紧密,因此对 url 的更改意味着类文件名、类名本身以及该类的任何实例都需要更改。对于更复杂的系统,这对我来说似乎非常耗时。

对于这个问题有哪些解决方案?在我看来,需要一个目录来存储 url 和控制器之间的关系,这样任何 url 都可以用来调用任何控制器,无论它们的名称是什么。因此,我们将有一个场地控制器和一个场地 url,当客户端请求更改 url 时,我们只需在目录中进行更改,将新的“场地”翻译为“场地”。

我认为最好的方法是在数据库表中,但这需要对每个用户请求进行额外的查询。数据库是实现目录的正确方法吗?目录是解决上述问题的最佳方法吗?这个问题从一开始就是一个问题吗???

In most of the tutorials for PHP MVC design structures, a router class is used to take user input and look up the right controller in order to process that input accurately. The input normally takes the form of a url. For example http://example.com/foo/bar/ would ask the router to find the controller named foo and fire the method bar.

PHP also has an auto-include function which requires a consistent naming system to used for your classes. For example, if I wanted to get an instance of the class Foo, I would need the file to be called Foo.php and inside would be a class called Foo.

Unfortunately, in tandem, these mechanisms place competing demands on the naming system. The url is very 'front facing' and as such, clients will often need it to reflect the content of a particular page. For example, if I have a page that gives directions to a venue, the client may need this page to be at http://example.com/venues/directions/. Later the content may change and the number of venues is reduced to 1 and now the client wishes the url to read http://example.com/venue/directions/. Obviously, this is a very trivial example but I think the need to change urls occasionally is clear.

Since the urls are very tightly connected to the controller classes, a change to a url means the class file name, the class name itself and any instances of that class will all require changing. For more complex systems this seems very time consuming, to me.

What sort of solutions are there to this problem? It seems to me that a directory of sorts will be necessary in which relations between urls and controllers are stored such that any url could be used to call any controller regardless of what either is named. Thus we would have a venues controller and a venues url and when the client requests a change in the url, we just make a change in the directory translating the new "venue" into "venues".

I think the best way to do this would be in a database table but this then requires an extra query for every user request. Is a database the right way to implement a directory? Is a directory even the best way to solve the above problem? Is this problem even a problem in the first place???

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

绮烟 2024-09-13 14:30:55

我看到的一些解决方案是显式指定到控制器/操作的路由“连接”。

例如,在 NiceDog 中,您可以指定

R('venues?/directions')
  ->controller('VenueController')
  ->action('directionsAction')
  ->on('GET');

允许正则表达式匹配 URL 之类的路由。 (上面的表达式将匹配 venue/directionsvenues/directions)我喜欢这种方法,因为它将控制器命名方案与 URL 命名方案解耦。

另一种更基于配置的方法是使用某种显式映射:

$routes = array(
    'venues?' =>
      array('controller'=>'VenueController','action'=>'indexAction'),
    'venues?/directions' =>
      array('controller'=>'VenueController','action'=>'directionsAction')
);

然后是一个简单的调度函数:

function dispatch($url,$routes) {
    foreach ($routes as $pattern=>$map) {
        if (preg_match($pattern,$url,$matches)) {
            $controller = new $map['controller']();
            $action = $map['action'];
            call_user_func_array(
              array($controller,$action),
              array_slice($matches,1)
            );
            return true;
        }
    }
    throw new Exception('Route not found.');
}

Some solutions I have seen to this is to explicitly specify a routing "connection" to a controller/action.

For example, in NiceDog, you can specify routes like

R('venues?/directions')
  ->controller('VenueController')
  ->action('directionsAction')
  ->on('GET');

Allowing a regular expression to match the URL. (The expression above will match venue/directions or venues/directions) I like this method, because it decouples the controller naming scheme from the URL naming scheme.

Another more configuration-based approach would be to have some kind of explicit mapping:

$routes = array(
    'venues?' =>
      array('controller'=>'VenueController','action'=>'indexAction'),
    'venues?/directions' =>
      array('controller'=>'VenueController','action'=>'directionsAction')
);

And then a simple dispatch function:

function dispatch($url,$routes) {
    foreach ($routes as $pattern=>$map) {
        if (preg_match($pattern,$url,$matches)) {
            $controller = new $map['controller']();
            $action = $map['action'];
            call_user_func_array(
              array($controller,$action),
              array_slice($matches,1)
            );
            return true;
        }
    }
    throw new Exception('Route not found.');
}
标点 2024-09-13 14:30:55

解决这个问题的一个好方法是 MVC 框架允许您指定自己的路由规则。例如,请参阅 CodeIgniter 框架文档中的 URI 路由

为了配合您的示例,这将允许您将 /venues/ 的请求重新映射到 /venue

A good way to solve this problem is for the MVC framework to allow you to specify your own routing rules. For example, see URI Routing in the CodeIgniter framework's documentation.

To go along with your example, this would allow you to remap requests for /venues/ to /venue.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文