人人都能看懂的全栈开发教程——前端控制器

人人都能看懂的全栈开发教程——前端控制器

Chris Yue No Comment
Posts

到目前为止已经明确过的需求已经全部实现了,趁现在还没有新的需求出来,我们可以回过头来看看我们的代码还有什么可以优化的。

一段代码在整个项目里的不同地方用到,叫做代码的复用。从我们开始项目之后,我们在不断重构代码,其中很大一部分成果是提高了代码的复用,比如说我们用来检查用户是否登录的 security/http/login-check.php 被好多个控制器文件引入,那么它的代码就被复用了好多次,类似的还有 pdo.php。为了不重复写代码,代码的复用率应该是要尽可能高的,而反例就是大量『复制粘贴』的重复代码,比如我们刚开始的代码。

先总结一下:把常用的代码,单独成一个文件,在需要它们的时候再引入,是一种常见的复用代码的方法。类似的还有把常用的代码封装在类的方法里,或者函数里,也是复用。这个思想经常用 DRY 来表示,也就是不要重复你自己(的工作,Don’t Repeat Yourself)。我们现在的代码已经比刚开始的时候进步了很多,但我们还有可能继续提高复用性吗?

先看看我们的代码还有哪里没有被复用呢?比如我们之前说,我们所有的控制器文件几乎都要先引入 security/http/login-check.php 文件来检查登录状态,这个动作本身是不是也是一种重复的代码,是不是也可以被复用呢?

另外,现在我们所有的请求都要求使用会话,所以会话功能看起来已经成了一种网站配置,而不是单独的跟某些控制器有关系了,我们能把调用 session_start 这个行为复用吗?

上面两个问题,实际上都可以通过一个叫『前端控制器』的『设计模式』来解决,它的主要做法就是,将所有的请求都先发送给一段代码来处理,这段代码就好像之前我们说过的『公因式』一样,把每个页面都需要执行的代码在这里执行,而每个页面所不同的部分,它就转发给每个控制器来自己完成。不多说,我们看看应该怎么做。

上面所说的『公因式』代码,我们一般叫『前端入口文件』,我们得先创建这个文件。但创建这个文件之前,我们先把目前的 web 目录,改名为 controller 也就是控制器目录,然后我们重新创建一个 web 目录,并且创建我们的前端入口文件 web/index.php

<?php
// $_GET 类似 $_POST 也是超级变量,但它是通过 URL 传的
// 比如下面要处理的 c 参数,就可以通过 http://localhost:8000/?c=xxx 的方式传
$controller = $_GET['c'] ?? 'index';
$filePath = sprintf('%s/../controller/%s.php', __DIR__, $controller);

// 通过控制器名生成控制器文件,但如果控制器文件并不存在,我们通过下面这种方式返回 404
if (!file_exists($filePath)) {
    header('HTTP/1.0 404 Not Found');

    die('Not Found');
}

session_start();

// 也不是所有的页面都需要检查是否登录,比如处理登录本身的地址
// 有了前端控制器,我们就可以在这里统一配置哪些地址需要检查登录,哪些不需要
if ('login' !== $controller) {
    require '../security/http/login-check.php';
}

require $filePath;

就这样,我们的前端控制器就做好了。这么处理完之后,我们的控制器文件就都又可以少一行引入 security/http/login-check.php 的代码了。

同样的,security/http/login-check.php 以及 controller/login.php 里的 session_start 调用也可以去掉了。

这个改动毫无疑问是会影响 MVC 里的 C 的,所以控制器代码肯定要做调整,我们也确实已经改过了。但要注意的是,因为我们修改了访问页面的方式,所以也会影响到 V,因为所有链接地址现在是在 V 里面写死的,比如说提交任务内容的表单的提交地址,就不再是 add.php 而是 /?c=add 了,这里大家需要将模板里所有提到链接地方都改掉。

如果一切顺利,我们的小网站依然能正常使用,大家修改过后可以实际测试一下。

除了网页可以用前端控制器,我们的命令也是可以的,只不过现在用意义也不是很大,就先略过了。

不过请读者注意的是,代码复用率虽然可以作为一个评判代码好坏的指标,但我的经验是不能只求代码复用率。代码复用的本质依然是拆分和抽象,被复用的代码应该是本身就可以独立出来负责一个任务的。如果是为了拆分而拆分,很有可能到最后自己都不知道想关注的代码写在什么地方,反而会增加维护难度。

本章节的完整代码请见这里

人人都能看懂的全栈开发教程——前端控制器 by Chris Yue is licensed under a Creative Commons Attribution-NonCommercial-NoDerivatives 4.0 International License.

微信赞赏码

写作累,服务器还越来越贵
求分担,祝愿好人一生平安
天使打赏人

发表评论

61 + = 66