URI的控制器不可调用,使用注释

时间:2014-03-26 09:02:48

标签: symfony capifony

我有一个返回500的symfony2控制器,带有这个日志条目:

[2014-03-26 01:25:48] request.INFO: Matched route "searchtempestsite_direct_sponsored" (parameters: "_controller": "SearchTempest\Bundle\SiteBundle\Controller\SearchController::DirectResultsSponsoredAction", "_route": "searchtempestsite_direct_sponsored") [] []
[2014-03-26 01:25:48] request.CRITICAL: Uncaught PHP Exception InvalidArgumentException: "The controller for URI "/search/direct/sponsored" is not callable." at [...]/releases/20140326082503/vendor/symfony/symfony/src/Symfony/Component/HttpKernel/Controller/ControllerResolver.php line 82 {"exception":"[object] (InvalidArgumentException: The controller for URI \"/search/direct/sponsored\" is not callable. at [...]/releases/20140326082503/vendor/symfony/symfony/src/Symfony/Component/HttpKernel/Controller/ControllerResolver.php:82)"} []

控制器操作定义为

/**
 * Display the Sponsored Results frame in Direct Results
 *
 * @return Symfony\Component\HttpFoundation\Response
 *
 * @Route("/search/direct/sponsored", name="searchtempestsite_direct_sponsored")
 */
public function DirectResultsSponsoredAction()
{
    $response = $this->get('legacy_bridge')
        ->request('direct_sponsored.php');

    $parameters = $response->getTemplateParameterBag();
    $content = $this->renderView(
        'SearchTempestSiteBundle:Search:directSponsored.html.twig',
        $parameters->all()
    );
    $response->setContent($content);

    return $response;
}

奇怪的是,在我的本地测试服务器上,一切都在dev和prod模式下正常工作。只有当我尝试使用capifony将其部署到生产服务器时才会出现此错误。但是,在同一控制器下定义的所有其他路由都正常工作。只有这个新的失败。这是一条工作路线:

/**
 * Display the Direct Results index
 *
 * @return Symfony\Component\HttpFoundation\Response
 *
 * @Route("/search/direct", name="searchtempestsite_direct")
 */
public function DirectResultsAction()
{
    $response = $this->get('legacy_bridge')
        ->request('adv_control.php');

    $parameters = $response->getTemplateParameterBag();

    $content = $this->renderView(
        'SearchTempestSiteBundle:Search:directResults.html.twig',
        $parameters->all()
    );
    $response->setContent($content);

    return $response;
}

我已经尝试更改路径(从/ search / direct / spons到/ search / direct_sponsored),但我仍然在新路径上收到相同的500错误。 (当然,错误中有新路径。)

除此之外,我还有点想要尝试的东西,而不是深入研究Symfony和Sensio代码的内容,以追踪它如何协调这些注释。据推测,这与安装到服务器有关,因为它在本地工作,但据我所知,一切都应该是相同的。两者都使用composer来安装依赖项,因此所有供应商代码都应该相同。我们不会在发布到服务器之间共享缓存,因此它正在使用新缓存。 (Capifony确实调用app / console cache:warmup --env = prod。)

听起来通常这个错误是由于路由yml中的控制器规范与Action函数的名称不匹配,或者是不公开的函数。这两个都不适用。

我很乐意提供所要求的任何其他信息。

编辑:它现在正在运作,虽然我没有改变任何东西。我认为正在发生的事情与Capifony的multistage extension有关。我们正在运行三个阶段(开发,测试,产品)。我一直在开发阶段对此进行测试,但我一时兴起将其部署到其他阶段,看看是否会产生任何影响。它起初没有,但在我部署到所有三个之后,当我重新部署到其中任何一个时,路线开始工作。

编辑2:多阶段是大多数问题,但还有更多问题。请参阅下面的答案。

1 个答案:

答案 0 :(得分:3)

事实证明问题是由于ApcClassLoader。 app.php中的这两行指示sf2使用APC来缓存应用程序使用的各种类的位置(文件系统路径):

$loader = new ApcClassLoader('sf2', $loader);
$loader->register(true);

您应该将sf2更改为唯一的前缀,以避免缓存键冲突。我们这样做了,但使用了相同的' unique'我们每个阶段的前缀,这意味着当我们运行部署并清除apc缓存时,无论先访问哪个阶段都会在缓存中设置文件位置,然后这些文件将用于所有阶段。由于它是一个繁忙的网站,这意味着生产阶段文件最终被用于其他阶段。

解决方案应该是为每个阶段简单地部署单独版本的app.php,并使用单独的前缀。 (或者传入一个变量作为前缀;但是你想要这样做。)但是,我还发现,即使我们清除了APC缓存,也很有可能同一阶段的先前版本污染了缓存([如此处所述] ] [1])部署后立即。我目前无法解释为什么会发生这种情况,因为即使我们在清算之前添加了延迟,似乎也会发生这种情况,以防任何请求正在进行中。

所以现在,我们只是使用composer而不是apc来保存类映射,如"使用Composer的类映射功能"部分:http://symfony.com/doc/current/book/performance.html

编辑:啊,这解释了最后一点,即使新版本发布后,早期版本如何污染缓存:https://stackoverflow.com/a/23419954/160565。我们使用符号链接进行部署,PHP正在缓存旧的符号链接路由,导致先前的部署在更新符号链接之前重新填充缓存。那里的答案解释了如何解决这个问题。