【问题标题】:"Proper" separation/difference between index.php and front controllerindex.php 和前端控制器之间的“正确”分离/差异
【发布时间】:2013-12-15 03:20:28
【问题描述】:

对于 PHP MVC 应用程序,index.php 文件和前端控制器的工作有什么区别?前端控制器是在index.php 中,还是在单独的文件中?我如何将两者分开并让它们一起工作?前端控制器是否应该是一个类(或像它自己的实体)? (如果是这样,那么 index.php 会实例化前端控制器吗?)

我知道他们必须“设置环境”,其中包括定义一些常量等,但是什么是什么? (——自动加载器、调试工具等)

我看到了这个:MVC with a front controller confusion,但这并不能解决index.php和前置控制器之间的差异问题。

【问题讨论】:

  • 此答案太短,无法作为答案发布。您真的应该阅读 MVC 的结构,特别是在与 PHP 一起使用时。在index.php 中初始化front-controller 的实例,故事结束。
  • 所以你是说index.php 所做的只是初始化front-controller?
  • 是的,这正是我要说的。你想让它做更多的事情吗?如果您的front-controller 很好并且已经完成,它应该可以按预期工作,并在构造函数完成后呈现您的页面。
  • @Andreas Bjørn 谢谢,因为这就是我所要求的,所以它不会太短而不能作为答案发布
  • 在这种情况下,我会将其作为答案发布。

标签: php design-patterns front-controller


【解决方案1】:

Index.php 应该初始化应用程序并调用将路由解密为控制器和动作的东西,然后运行它们。看看 Yii、Symfony、CodeIgniter、CakePHP,看看他们做了什么。都略有不同,但原理相同。

一个来自 Yii 的 index.php 的例子来说明这一点:

<?php

$yii=dirname(__FILE__).'/../../framework/yii.php';
$config=dirname(__FILE__).'/protected/config/main.php';
require_once($yii);
Yii::createWebApplication($config)->run();

$config 被传递给作为前端控制器的 Web 应用程序。

【讨论】:

  • 初始化到什么程度?
  • 例如,我有一个 Yii 应用程序,我根据它是 Web 请求还是控制台请求、测试、开发还是生产环境来扩展/自定义初始化。所以相关的 index.php 设置了一些常量,加载了一个初始化类,然后加载了相关的 Yii 应用程序类,传递了配置,然后运行它。就是这样。
  • 在这种情况下,index.php 和前置控制器之间有什么区别?
  • 前端控制器根据URL决定调用哪个控制器和动作。它构建一个请求并将其传递给控制器​​。它还可以接收呈现的响应并执行额外的工作。我同意 Andreas 的观点,您应该阅读 PHP 中的 MVC,并查看各种框架。例如,PHP 的一个设计目标是尽量减少必须加载的框架代码量,因为它必须随每个请求一起加载。
  • @jasonszhao 来吧,我们已经告诉你下一步该做什么,阅读、学习和繁荣。你 10 分钟前刚刚向我解释了路由是做什么的,你怎么能问大卫它是做什么的?我的朋友,胜利没有捷径可走,你必须为之努力。
【解决方案2】:

您确实应该阅读 MVC 的结构,尤其是与 PHP 一起使用时。在 index.php 中初始化一个前端控制器实例,如果该过程是前端控制器初始化过程的一部分,它应该呈现您的页面 (__constructor())。

【讨论】:

  • 1)我觉得对话真的没必要
  • 2) 您的回答与 davidfurber 的完全矛盾,所以我会等待再决定接受哪一个
  • 1) 好的,根据您的喜好修正答案。 2)我的回答与@davidfurber 的回答并不矛盾——他似乎只是认为应该在索引文件中定义路由,而我没有。可能是偏好问题。 3)如果你不知道什么是路由,你应该阅读使用 PHP 和 MVC,因为它超出了你的问题范围。
  • 表示处理请求(主要是URI)并包含相应的文件,尤其是控制器
  • 我不是建议在 index.php 中定义路由,只是 index.php 会加载一个初始化器,然后将其传递给前端控制器。 github.com/yiisoft/yii/blob/master/demos/blog/index.php
【解决方案3】:

实际上,index.php 根本不应该包含任何有意义的代码,因为它只是您网站的一部分,位于网络服务器的 DOCUMENT_ROOT 内。它的内容实际上应该类似于:

<?php 

    require '../application/bootstrap.php';

它应该只包含DOCUMENT_ROOT 之外的文件。仅此而已。

这样,如果出现严重错误(例如,服务器更新后 php 扩展失败)并且访问者接触到原始 php 代码,它不会泄露任何敏感细节。

Front Controller 的重点是处理所有用户输入,将其转换为可消耗的形式,并在此基础上调度命令(通常以对对象的方法调用的形式)。在像 Java 这样的语言中,所有东西都必须包含在一个类中,前端控制器就是一个类。但是在php中你没有这个限制。

相反,前端控制器最终将成为应用程序引导阶段的一部分:

// --- snip --- 
// the autoloader has been initialized already a bit earlier

$router = new Router;
$router->loadConfig($configuration);

$request = new Request;
$request->setUri($GET['url']); 
// could also be $_SERVER['PATH_INFO'] or other
// depends on how url rewrite is set up

$router->route($request);
// the request instance is populated with data from first matching route

$class = $request->getParameter('resource');
$command = $request->getMethod() . $request->getParameter('action');

if (class_exists($class)) {
    $instance = new $class;
    $instance->{$command}($request);
    // you dispatch to the proper class's method 
}

// --- snip --- 
// then there will be some other code, unrelated to front controller

另外,您应该记住,前端控制器的概念既不是为尝试实现 MVC 或受 MVC 启发的架构的应用程序而设计的,也不是为应用程序所要求的。

【讨论】:

  • 哇!你让我明白了非常很好的答案,谢谢!
  • 在这种情况下,为什么不让 .htaccess 将所有请求转发到引导脚本并取消 index.php?
  • davidfurber,我不能 100% 确定这一点,但我认为网络服务器无法访问指定文件夹之外的文件。否则,在我看来,这将是一个相当大的安全问题。这个想法是让网络服务器调用 index.php,然后 PHP 可以从那里获取它并访问它需要的任何内容。
  • @davidfurber ,然后,如果 mod_php 加载失败,您将看到 bootstrap.php 文件,而不是索引。这会让你回到广场 nr.1
  • @Linus 仅在该文件中完成的是各种“路径常量”的定义。我个人 会将其描述为 不好的做法,原因有两个。我的情况是mod_php(或其替代方案),这至少会泄露有关您的应用程序目录结构的部分知识。另一个问题与常量本身有关——它们引入了不可变的全局状态。这意味着代码中某处的某个类正在使用您没有提供的信息。而且你不知道在哪里以及如何,
猜你喜欢
  • 2015-03-31
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-02-12
  • 2020-08-09
  • 2014-09-13
  • 2016-05-12
  • 1970-01-01
相关资源
最近更新 更多