symfony BasePath属性在请求对象中始终为空,用于PHPUnit测试

kuuvgm7e  于 2023-01-13  发布在  PHP
关注(0)|答案(2)|浏览(115)

我有一个控制器有一个动作,看起来像这样:

/**
 * @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字符串,但它在浏览器上运行得很好。

nimxete2

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)检索项目目录

function doSomethingAction(ParameterBagInterface $params) {
    $projectDir = $params->get('kernel.project_dir');
}

或通过容器(Symfony 3)也可参见:new in symfony 3.3: A simpler way to get the project root directory

function doSomethingAction() {
    $projectDir = $this->getParameter('kernel.project_dir'); 
}
gzjq41n4

gzjq41n42#

在我的例子中,我必须inyect RequestStack $stack并访问主请求,之后我的“BasePath”就有了值,这是因为我在子请求中,我必须访问请求的顶层。
这篇文章帮助我理解:Symfony2 - get main request's current route in twig partial/subrequest

/**
     * @Route("/myroute", name="myroute")
     */
    public function myroute(RequestStack $stack)
    {
        $request = $stack->getMainRequest();
        $route = $request->getPathInfo();
    }

相关问题