我有一个控制器有一个动作,看起来像这样:
/**
* @Route("/my_route_path", name="my_route_name")
*/
public function doSomethingAction(Request $request)
{
$myPath = $request->getScheme().'://'.$request->getHttpHost().''.$request->getBasePath();
$data = file_get_contents($myPath. '/data_folder/data.json');
return $this->render('@Entry/my_template.html.twig', array(
'data' => json_decode($data, true)
));
}
我为这个控制器创建了一个功能测试,如下所示:
/** @test */
public function doSomething_should_success()
{
$client = static::createClient();
$crawler = $client->request('GET', '/my_route_path');
$this->assertEquals(200, $client->getResponse()->getStatusCode());
}
但我不能运行功能测试,我仍然得到:Failed asserting that 500 is identical to 200
所以,在我检查test.log文件后,我发现这个错误:file_get_contents(http://localhost/data_folder/data.json) : failed to open stream
现在,问题来自$request->getBasePath()
,因为始终包含空字符串,但预期行为是返回PATH_TO_MY_PROJECT_FOLDER\web
,在我的情况下必须返回projects\web_apps\MY_PROJECT_FOLDER_NAME\web
所以,简单的问题是:为什么request对象在单元测试中总是包含一个空的basePath字符串,但它在浏览器上运行得很好。
2条答案
按热度按时间nimxete21#
Request
对象帮助您处理客户端的请求,它类似于GET /my_route_path
,加上许多头文件和一个指向的服务器。Web服务器将这些信息传递给php和symfony,symfony将其转换为
Request
对象,Symfony通常有一个入口点,即public/index.php
(symfony 4)或web/app.php
(symfony 3),假定为/
或/basePath/
(基本路径将由Web服务器传递并由Symfony处理)。Symfony将生成一个Request对象,其中基本路径基本上是抽象出来的,每当你生成一个url(通过
Controller::generateUrl
)时,基本路径都会被考虑在内。这就是为什么基本路径对Request很重要。实际上,在Request函数的注解中对此进行了很好的描述:获取基本路径与获取路径信息。
然而,这只涉及面向公众的URL,与您如何构建项目以及项目位于何处无关,因为这与请求完全无关(关注点和内容的分离)。
所以我猜,您实际上是在寻找项目的 * 根目录 *。
要找到你的项目目录的位置,有一个非常基本的版本,你可以直接使用PHP magic var
__DIR__
,它包含了当前脚本文件所在的目录,你可以从那里导航。由于控制器通常位于projectdir/src/Controller/TheController.php
,__DIR__.'/../..
会给予你projectdir
。那可不干净。更好的说法是根据您使用的symfony版本,您应该通过ParameterBagInterface (symfony 4)检索项目目录
或通过容器(Symfony 3)也可参见:new in symfony 3.3: A simpler way to get the project root directory
gzjq41n42#
在我的例子中,我必须inyect
RequestStack $stack
并访问主请求,之后我的“BasePath”就有了值,这是因为我在子请求中,我必须访问请求的顶层。这篇文章帮助我理解:Symfony2 - get main request's current route in twig partial/subrequest