单一入口应用程序的解释? php
咱们先来看看传统的 web开发的 应用。
有如下两个php文件
news.php 显示新闻列表
news_edit.php 显示新闻编辑页面
这两个页面不但分别实现了两个功能,还成为了应用程序的两个入口。 web
到底什么才是入口呢?
打个比方,你们上 WC,都是男生进一个门,女生进一个门。这两个门就是 WC 的两个入口。 数据库
呵呵,上面的例子应该很好理解吧。那稍微变换一下,单一入口的概念就很容易理解了。
如今咱们是进一个公共 WC,无论男女都是从最外面的入口进入,交了钱之后才分别进两个门。那最外面的入口就是这个 WC 的单一入口。 apache
因此单一入口的应用程序实际上就是说用一个文件处理全部的 HTTP 请求。例如不论是新闻列表功能仍是新闻编辑功能,都是从浏览器访问 index.php 文件。这个 index.php 文件就是这个应用程序的单一入口。 浏览器
index.php 如何知道用户是要使用哪个功能呢? 安全
很简单,咱们访问 index.php 时跟上一个特定的参数就好了。例如 index.php?action=news 就是显示新闻列表,而 index.php?action=news_edit 就是新闻编辑。 服务器
而在 index.php 里面,仅用两行代码就能够实现这种效果。
<?php
$action = $_GET['action'] == '' ? 'index' : $_GET['action'];
include('files/' . $action . '.php');
?> 框架
上面的代码中,第一行是从 url 中取出 action 参数。若是没有提供 action 参数,就设置一个默认的 'index' 做为参数。
第二行代码就是根据 $action 参数调用不一样的代码文件,从而实现单一入口对应不一样功能的效果。 函数
单一入口应用程序的入口文件很复杂? 工具
有些朋友可能觉得单一入口程序的 index.php 会像面条同样复杂,实际上是误解。
例如我如今的应用程序入口文件只有下面几行:
<?php
define('APP', realpath('../libs/website'));
define('LANG', 'gb2312');
define('DEBUG', 1);
require('../libs/flea1/basic.php');
run();
?>
足够简单了吧?
固然了,在 index.php 里面写上一长串 switch case 绝对是拙劣的实现方式。但这纯粹是开发者本身的设计和实现问题,而不是单一入口应用程序这种设计思想的问题。
补充说明: 这里提到 switch case 并非说用了 switch 就表明“落后”、“土气”等。只是说在 index.php 这个入口程序里面写上一堆 switch case 不利于程序的修改和维护,因此是一种很差的用法。
单一入口应用程序的设计思想
当web服务器(apache或者iis)收到一个http请求时,会解析该请求,肯定要访问哪个文件。例如 http://www.xxx.com/news.php 的解析结果就是要求web服务器解析 news.php 文件,并返回结果给浏览器。如今看看单一入口应用程序的 index.php 文件,就会发现 index.php 实际上根据 url 参数进行了第二次解析。
完成这个解析的程序通常称为 Dispatcher(中文的准确翻译我也不知道),大概意思就是将不一样的请求转发到不一样的处理程序进行处理。
在单一入口应用程序中,index.php 和 web服务器一块儿构成了一个 Dispatcher,根据 http 请求和 url 参数来肯定请求的处理程序。
了解了 Dispatcher 的概念后,咱们能够发现前面提到的两行代码实际上就是一个最简单的 Dispatcher 实现:
<?php
$action = $_GET['action'] == '' ? 'index' : $_GET['action'];
include('files/' . $action . '.php');
?>
诚然,对于一个安全、健壮的应用程序,Dispatcher 确定不是上面那么简单。在调用实际代码前,还会加上各类判断、安全性检查等。例如判断 url 指定的功能是否能够访问以及 url 中包含了无效的参数。
看到这里,朋友们确定会说:单一入口程序就多了就这样一个 dispatcher ,和我直接作成 news.php、news_edit.php 等单个文件相比有什么好处啊?
单一入口应用程序的优点
单一入口应用程序的全部http请求都是经过 index.php 接收并转发到功能代码去的,因此咱们在 index.php 里面就能完成许多实际工做。
这里我只拿安全性检查为例详细说明一下:
因为全部的 http 请求都由 index.php 接收,因此能够进行集中的安全性检查。若是不是单一入口,那么开发者就必须记得在每个文件的开始加上安全性检查代码(固然,安全性检查代码能够写到另外一个文件中,只须要include进来就能够了)。
但我想你们都是懒人,也许记性也很差,不免有忘记的时候。所以要记得在每个文件前面都加上必要的include可不是件容易作到的事情。
与安全性检查相似。在入口里,咱们还能够对url参数和post进行必要的检查和特殊字符过滤、记录日志、访问统计等等各类能够集中处理的任务。
“咦,搞这么多功能,不是会把 index.php 搞得很复杂吗?”
“不会的。只须要把各类功能写到单独的文件,而后在index.php里面include进来就能够了!”
能够看出,因为这些工做都被集中到了 index.php 来完成,能够减轻咱们维护其余功能代码的难度。例如在10个文件中保持头部的几个include都一致可不是件让人愉快的事情。
单一入口应用程序的缺点
任何事情都有两面性,单一入口应用程序也不例外。因为全部 http 请求都是针对 index.php,因此应用程序的 url 看起来确实不那么美观。特别是对搜索引擎来讲很不友好。
要解决这个问题,能够采用 url 重写、PATHINFO 等方式。但我我的更推荐在前台页面不使用单一入口方式,而是保持多个文件入口。或者二者混用。例如新闻列表采用单独的 news.php 显示,而用户注册、发表信息等则采用单一入口。由于对于网站拥有者来讲,新闻列表、新闻显示页面才是须要搜索引擎关注的高价值目标,而用户注册页面等交互性功能则根本没有收录的价值。
有朋友提到单一入口的应用程序会有很长一串参数,那么咱们分析一下下面这个 url:
index.php?url=news&news_id=123&page=2&sort=title
若是改成直接访问 news.php,也只不过省掉了 url=news 这一个参数而已。
因此认为单一入口的应用程序 url 太复杂是没有道理的。
如何组织单一入口应用程序的功能代码?
单一入口应用程序最大的挑战来自于如何合理组织各个功能的处理代码。但只要遵循必定的步骤,也能够轻松的解决掉这个难题。
首先,对于应用程序的功能要作出一个合理的分解。例如后台的新闻栏目可能包含“添加新闻”、“编辑新闻”、“删除新闻”等多个功能。这时咱们就能够将这一组逻辑上关联的功能组合到一个功能模块中,称为“新闻管理”模块。
按照上面的方法整理完应用程序的功能,咱们就会获得多个功能模块,而每一个模块又是由多个功能组成。(实际上,即使不是单一入口应用程序,功能的整理也是必须的步骤。)
整理完功能后,咱们就须要肯定如何存放各个功能的代码。这里我推荐两种方式:
一、每一个功能模块一个子目录,目录里的每个文件就是一个功能的实现代码。
这种方式的好处是每一个功能的代码都互相隔离,很是便于多人协做。缺点是每一个功能之间共享代码和数据不那么方便。例如新闻管理模块中的全部功能都须要一个 “取出新闻栏目记录”的功能,那么采用这种多个独立文件的组织方式,“取出新闻栏目记录”就只能写在另外一个文件中,而后由须要该功能的文件include 进去。
二、每一个模块一个文件,模块中的每一个功能写成一个函数或者一个类方法。
好处不用多说了,很是便于共享代码和数据。缺点就是若是几我的同时改,容易发生冲突。不过借助版本控制软件和差别比较合并工具,冲突仍是很容易解决的。
好了,咱们的功能代码都肯定存放方式了。那么如何调用呢?
index.php 如何调用功能代码?
调用首先就是要设计一个规则,而后让 index.php 根据这个规则来搜索和调用功能代码。就我本身来讲,我老是使用 $_GET['url'] 来指定要调用的功能模块,而 $_GET['action'] 来指定该模块的特定功能。所以个人应用程序会使用以下的 url 地址:
index.php?url=news&action=edit
以为两个参数太多了?那可使用 index.php?func=news.edit 这样的 url。只须要将 news.edit 拆开为 news 和 edit 就好了。
“嘿嘿,那我故意搞一个 index.php?url=news&action=xxx,看你的应用程序还能运行?”
很显然,这样的 url 只会使得 index.php 没法找到须要的功能代码,最后报告错误。可是这和你在浏览器中访问 newsxxx.php 这个并不存在的文件有什么本质区别呢?
相反,我还可让 index.php 在发现找不到须要的功能代码时显示一个漂亮的出错页面,并提供一个返回网站首页的链接。
在实际开发中,我倾向于将一些基本服务从应用程序中抽取出来,造成一个应用程序框架。这个框架一般会包含一个 Dispatcher、基本的数据库访问服务、模版引擎、经常使用的辅助功能等。因为有了一个框架,因此我能够更加让 Dispatcher 更加灵活。例如能够对某些功能模块应用权限检查,而另外一些则不检查。
进一步了解单一入口应用程序
要深入理解一个事物,本身尝试一下是最好的办法。
你能够选择本身实现一个 Dispatcher 以及相应的各类规则,或者选择一个现有的应用程序框架。但更好的方式仍是首先尝试一下现有的框架,而后再本身尝试实现一个相似的。这样能够在最短的时间内得到最多的收获。
目前绝大多数 php 应用程序框架都是单一入口的,并采用了 MVC 模式(很遗憾,因为 MVC 实在太复杂,而且和单一入口应用程序也没有必然联系。感兴趣的朋友能够 google 一下相关资料)。