igorw / cgi-http-kernel
从HttpKernelInterface到CGI的适配器。
Requires
- symfony/http-kernel: ~2.1
- symfony/process: ~2.1
Requires (Dev)
- silex/silex: 1.0.*@dev
This package is not auto-updated.
Last update: 2024-09-14 13:23:21 UTC
README
从HttpKernelInterface到CGI的适配器。
HttpKernelInterface是个谎言
你认为你需要重写整个应用来使用HttpFoundation以从HttpKernelInterface功能测试中受益吗?
但是,事实是,你根本不需要这样做。一些非常聪明的人发明了这个叫做CGI(通用网关接口)的东西,它定义了Web服务器和Web应用之间的接口。它很棒,因为它使用UNIX管道进行通信,这意味着它也非常容易假装成Web服务器,只需手动在命令行中调用应用并传递任何输入和环境变量。
在PHP中,这可以通过使用随几乎所有PHP发行版一起提供的php-cgi
来实现。在命令行中调用它的最基本方法是这个:
$ php-cgi hello.php
如果你想学习如何进行更高级的操作,请阅读该CGI规范。
那么这和HttpKernelInterface有什么关系?CGI和这个接口基本上做的是同一件事,它们抽象了Web服务器和应用程序之间的通信。内核接口在PHP内部执行此操作,而CGI以语言无关的方式执行。
CgiHttpKernel在这两个接口之间进行转换。作为库的用户,你就像它与一个真正的HttpKernelInterface应用交互一样与之交互,但实际上它会在后台调用命令行中的php-cgi
,解析输出并返回一个Response
实例。
例如
$kernel = new CgiHttpKernel(__DIR__.'/../phpBB');
$request = Request::create('/index.php');
$response = $kernel->handle($request);
var_dump($response->getContent());
如果你想让所有请求都通过一个前端控制器,你可以在构造函数中传递第二个参数。
$kernel = new CgiHttpKernel(__DIR__.'/../web', 'app.php');
$request = Request::create('/foo');
$response = $kernel->handle($request);
然而,真正的力量来自于使用与HttpKernelInterface集成的库,例如Symfony\Component\HttpKernel\Client
。
$kernel = new CgiHttpKernel(__DIR__.'/../phpBB');
$client = new Client($kernel);
$crawler = $client->request('GET', '/index.php');
$this->assertGreaterThan(0, $crawler->filter('.topiclist')->count());
这真的是个谎言吗?
并不是真的。CgiHttpKernel只适用于功能测试,因为它相当慢。它之所以慢,是因为它必须为每个请求生成一个新的进程。这也是一些非常聪明的人发明FastCGI的原因,它类似于CGI但更快。
FastCGI允许应用程序启动一个长时间运行的进程,该进程监听端口,因此没有进程创建开销。在PHP世界中,这通常由PHP-FPM(即FastCGI进程管理器)管理。
FastCGI适用于生产环境,但不适用于测试,因为它需要在单独的进程中运行,监听端口,需要配置等。
然而,存在一个FcgiHttpKernel,它将此项目的思想迁移到了FastCGI。它实际上可能对测试很有用。
何时使用CgiHttpKernel?
它主要用于编写旧版应用程序的功能测试。这可能会让你有信心重构旧代码,而不用担心破坏东西。
祝你好运。
具体细节
属性
请求属性被序列化并通过SYMFONY_ATTRIBUTES
环境变量提供给目标脚本。这意味着它可以通过以下方式获取原始属性:
$attributes = unserialize($_SERVER['SYMFONY_ATTRIBUTES']);