前置控制器

编辑本页

警告:您正在浏览的文档欧宝体育电话欧宝娱乐app下载地址Symfony 2.6,现已不再维护。

本页的更新版本用于Sy欧宝娱乐app下载地址mfony 6.2(当前稳定版本)。

前置控制器

到目前为止,我们的应用程序很简单,因为只有一个页面。为了让事情变得有趣一点,让我们疯狂地添加另一页来告别:

1 2 3 4 5 6 7 8 9 10 11
/ /框架/ bye.phprequire_once__DIR__“/供应商/ autoload.php”使用欧宝娱乐app下载地址组件HttpFoundation请求使用欧宝娱乐app下载地址组件HttpFoundation响应请求=请求::createFromGlobals ();响应响应(“再见!”);响应->send ();

正如您自己所看到的,许多代码与我们为第一页编写的代码完全相同。让我们提取可以在所有页面之间共享的公共代码。代码共享听起来像是创建我们第一个“真正的”框架的好计划!

PHP进行重构的方法可能是创建一个包含文件:

1 2 3 4 5 6 7 8 9
/ /框架/ init.phprequire_once__DIR__“/供应商/ autoload.php”使用欧宝娱乐app下载地址组件HttpFoundation请求使用欧宝娱乐app下载地址组件HttpFoundation响应请求=请求::createFromGlobals ();响应反应();

让我们来看看它的实际情况:

1 2 3 4 5 6 7 8
/ /框架/ index . phprequire_once__DIR__' / init.php '输入请求->get (“名字”“世界”);响应->setContent (sprintf (“你好% s”,:输入ENT_QUOTES,“utf - 8”)));响应->send ();

在“再见”页面:

1 2 3 4 5 6
/ /框架/ bye.phprequire_once__DIR__' / init.php '响应->setContent (“再见!”);响应->send ();

我们确实将大部分共享代码移到了一个中心位置,但感觉不像是一个好的抽象,不是吗?我们仍然有send ()方法,我们的页面看起来不像模板,我们仍然不能正确地测试这段代码。

此外,添加一个新页面意味着我们需要创建一个新的PHP脚本,该脚本的名称将通过URL (http://127.0.0.1:4321/bye.php): PHP脚本名和客户端URL之间有一个直接的映射。这是因为请求的分派是由web服务器直接完成的。为了获得更好的灵活性,将这个调度移到我们的代码中可能是个好主意。这可以通过将所有客户端请求路由到单个PHP脚本轻松实现。

提示

将单个PHP脚本暴露给最终用户是一种称为“前端控制器_”的设计模式。

这样的脚本可能如下所示:

12 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
/ /框架/ front.phprequire_once__DIR__“/供应商/ autoload.php”使用欧宝娱乐app下载地址组件HttpFoundation请求使用欧宝娱乐app下载地址组件HttpFoundation响应请求=请求::createFromGlobals ();响应反应();地图数组' /你好'= >__DIR__' / hello.php '' /再见'= >__DIR__' / bye.php ',);路径请求->getPathInfo ();如果收取地图路径))) {需要地图路径];}其他的响应->setStatusCode (404);响应->setContent (“没有找到”);}响应->send ();

这是一个新的例子hello.php脚本:

1 2 3 4
/ /框架/ hello.php输入请求->get (“名字”“世界”);响应->setContent (sprintf (“你好% s”,:输入ENT_QUOTES,“utf - 8”)));

front.php脚本,美元的地图关联URL路径和相应的PHP脚本路径。

作为奖励,如果客户端请求的路径没有在URL映射中定义,我们将返回一个自定义404页面;你现在可以控制你的网站了。

要访问页面,现在必须使用front.php脚本:

  • http://127.0.0.1:4321/front.php/hello?name=Fabien
  • http://127.0.0.1:4321/front.php/bye

/你好而且/再见是页面路径

提示

大多数web服务器,如Apache或nginx能够重写传入的url并删除前端控制器脚本,以便您的用户能够键入http://127.0.0.1:4321/hello?name=Fabien,看起来好多了。

诀窍在于要求::getPathInfo ()方法,该方法通过删除前端控制器脚本名称及其子目录来返回请求的路径(仅在需要时—参见上面的技巧)。

提示

你甚至不需要设置一个web服务器来测试代码。相反,替换$request = request::createFromGlobals();调用像这样的东西$request = request::create('/hello?name=Fabien');其中参数是要模拟的URL路径。

现在web服务器总是访问相同的脚本(front.php)对于所有页面,我们可以通过将所有其他PHP文件移出web根目录来进一步保护代码:

1 2 3 4 5 6 7 8 9 10 11
├──composer。Json├──composer。页面锁├──src│└──│├──hello.php│└──bye.php├──供应商│└──autoload.php└──web└──front.php

现在,配置您的web服务器根目录指向web /所有其他文件都不能从客户端访问了。

要在浏览器中测试更改(http://localhost:4321/?name=Fabien),运行PHP内置服务器:

1
$ php -S 127.0.0.1:4321 -t web/ web/front.php

请注意

要使这个新结构工作,您必须调整各种PHP文件中的一些路径;这些更改留给读者作为练习。

每一页中重复的最后一件事是调用setContent ().我们可以将所有页面转换为“模板”,只需回显内容并调用setContent ()直接从前端控制器脚本:

12 3 4 5 6 7 8 9 10 11 12 13 14 15
/ / example.com/web/front.php/ /……路径请求->getPathInfo ();如果收取地图路径])) {ob_start();包括地图路径];响应->setContent (ob_get_clean ());}其他的响应->setStatusCode (404);响应->setContent (“没有找到”);}/ /……

hello.php脚本现在可以转换为模板:

1 2 3 4 5
<!——example.com/src/pages/hello.php——- > < ?php的名字请求->get (“名字”“世界”? >你好<?php回声:的名字ENT_QUOTES,“utf - 8”? >

我们有了框架的第一个版本:

12 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
/ / example.com/web/front.phprequire_once__DIR__“/ . . /供应商/ autoload.php”使用欧宝娱乐app下载地址组件HttpFoundation请求使用欧宝娱乐app下载地址组件HttpFoundation响应请求=请求::createFromGlobals ();响应反应();地图数组' /你好'= >__DIR__“/ . . / src /页面/ hello.php”' /再见'= >__DIR__“/ . . / src /页面/ bye.php”,);路径请求->getPathInfo ();如果收取地图路径])) {ob_start();包括地图路径];响应->setContent (ob_get_clean ());}其他的响应->setStatusCode (404);响应->setContent (“没有找到”);}响应->send ();

添加新页面分为两个步骤:在映射中添加一个条目,并在中创建一个PHP模板src /页面/.方法从模板中获取请求数据美元的请求变量和调整响应头美元的反应变量。

请注意

如果您决定在这里停止,您可能可以通过将URL映射提取到配置文件来增强您的框架。

此工作,包括代码示例,是根据创作共用BY-SA 3.0许可证。