gpt4 book ai didi

php - MVC 中的路由、导航和状态

转载 作者:可可西里 更新时间:2023-11-01 00:47:34 25 4
gpt4 key购买 nike

我正在尝试使用 MVC 范例重构我的应用。

我的网站显示图表。 URL 的形式为

  • app.com/category1/chart1
  • app.com/category1/chart2
  • app.com/category2/chart1
  • app.com/category2/chart2

我正在使用 Apache Rewrite 将所有请求路由到 index.php,因此我在 PHP 中进行 URL 解析。

我正在进行一项持久的任务,即在选择某个页面时将 active 类添加到我的导航链接中。具体来说,我有类别级导航和图表级子导航。我的问题是,在保持 MVC 精神的同时做到这一点的最佳方法是什么?

在我重构之前,由于 nav 变得相对复杂,我决定将它放入一个数组中:

$nav = array(
'25th_monitoring' => array(
'title' => '25th Monitoring',
'charts' => array(
'month_over_month' => array(
'default' => 'month_over_month?who=total&deal=loan&prev='.date('MY', strtotime('-1 month')).'&cur='.date('MY'),
'title' => 'Month over Month'),
'cdu_tracker' => array(
'default' => 'cdu_tracker',
'title' => 'CDU Tracker')
)
),
'internet_connectivity' => array(
'title' => 'Internet Connectivity',
'default' => 'calc_end_to_end',
'charts' => array(
'calc_end_to_end' => array(
'default' => 'calc_end_to_end',
'title' => 'calc End to End'),
'quickcontent_requests' => array(
'default' => 'quickcontent_requests',
'title' => 'Quickcontent Requests')
)
)
);

同样,我需要知道当前类别和正在访问的当前图表。我的主导航是

<nav>
<ul>
<?php foreach ($nav as $category => $category_details): ?>
<li class='<?php echo ($current_category == $category) ? null : 'active'; ?>'>
<a href="<?php echo 'http://' . $_SERVER['SERVER_NAME'] . '/' . $category . '/' . reset(reset($category_details['charts'])); ?>"><?php echo $category_details['title']; ?></a>
</li>
<?php endforeach; ?>
</ul>
</nav>

和子导航类似,检查 current_chart 而不是 current_category。

之前,在解析过程中,我通过 / 分解 $_SERVER['REQUEST_URI'],并将片段分解为 $current_category$current_chart。我在 index.php 中这样做。现在,我觉得这不符合字体 Controller 的精神。来自 Symfony 2's docs 等引用文献,似乎每条路线都应该有自己的 Controller 。但是,我发现自己必须多次定义当前类别和图表,或者在模板文件本身(这似乎不符合 MVC 的精神)中,或者在模型中的任意函数中(然后必须由多个 Controller 调用,这似乎是多余的)。

此处的最佳做法是什么?

更新:这是我的前端 Controller 的样子:

// index.php
<?php
// Load libraries
require_once 'model.php';
require_once 'controllers.php';

// Route the request
$uri = str_replace('?'.$_SERVER['QUERY_STRING'], '', $_SERVER['REQUEST_URI']);
if (isset($_SERVER['HTTP_X_REQUESTED_WITH']) && (!empty($_GET)) && $_GET['action'] == 'get_data') {

$function = $_GET['chart'] . "_data";
$dataJSON = call_user_func($function);
header('Content-type: application/json');
echo $dataJSON;

} elseif ( $uri == '/' ) {
index_action();

} elseif ( $uri == '/25th_monitoring/month_over_month' ) {
month_over_month_action();

} elseif ( $uri == '/25th_monitoring/cdu_tracker' ) {
cdu_tracker_action();

} elseif ( $uri == '/internet_connectivity/intexcalc_end_to_end' ) {
intexcalc_end_to_end_action();

} elseif ( $uri == '/internet_connectivity/quickcontent_requests' ) {
quickcontent_requests_action();

} else {
header('Status: 404 Not Found');
echo '<html><body><h1>Page Not Found</h1></body></html>';
}

?>

似乎当 month_over_month_action() 被调用时,例如,由于 Controller 知道 current_chart 是 month_over_month,它应该传递它。这就是我被绊倒的地方。

最佳答案

这方面没有“最佳实践”。虽然,有一些比其他更常用,还有一些是非常糟糕的想法(不幸的是,这两组往往会重叠)

MVC 中的路由

虽然从技术上讲这不是 MVC 设计模式的一部分,但在应用于 Web 时,您的应用程序需要知道要初始化哪个 Controller 以及调用什么方法。

正在做 explode()收集这类信息不是个好主意。它既难以调试又难以维护。更好的解决方案是使用正则表达式。

基本上,您最终会得到一个路由列表,其中包含一个正则表达式和一些回退值。您遍历该列表并在拳头匹配上提取数据并应用默认值,其中缺少数据。

这种方法还可以让您在参数顺序方面拥有更广泛的可能性。

为了使解决方案更易于使用,您还可以添加将符号字符串转换为正则表达式的功能。

例如(取 self 的一些单元测试):

  • 符号: test[/:id]
    表达式:#^/test(:?/(?P<id>[^/\.,;?\n]+))?$#

  • 符号: [[/:minor]/:major]
    表达式:#^(:?(:?/(?P<minor>[^/\.,;?\n]+))?/(?P<major>[^/\.,;?\n]+))?$#

  • 符号: user/:id/:nickname
    表达式:#^/user/(?P<id>[^/\.,;?\n]+)/(?P<nickname>[^/\.,;?\n]+)$#

虽然创建这样的生成器并不那么容易,但它可以很好地重用。恕我直言,花在制作它上的时间是值得的。此外,使用 (?P<key>expression)正则表达式中的构造为您提供了来自匹配路由的非常有用的键值对数组。

菜单和 MVC

决定将哪个菜单项突出显示为 active应该始终是当前 View 实例的责任。

更复杂的问题是做出此类决定所需的信息从何而来。 View 实例可用的数据有两个来源:由 Controller 传递给 View 的信息和数据,即从模型层请求的 View 。

The controller in MVC takes the user's input and, based on this input, it changes the state of current view and model layer, by passing said values. Controller should not be extracting information from model layer.

恕我直言,在这种情况下更好的方法是在模型层上中继有关菜单内容和其中当前事件元素的信息。虽然可以对 View 中的当前事件元素进行硬编码并中继 Controller 传递的信息,但 MVC 通常用于大型应用程序,这种做法最终会伤害到您。

The view in MVC design pattern is not a dumb template. It's a structure, that is responsible for UI logic. In context of Web that would mean creating a response from multiple template, when necessary, or sometimes just simply sending an HTTP location header.

关于php - MVC 中的路由、导航和状态,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14596934/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com