URI的控制器无法使用注释进行调用 [英] The controller for URI is not callable, using annotations

查看:68
本文介绍了URI的控制器无法使用注释进行调用的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个symfony2控制器,该控制器返回500,并带有以下日志条目:

I have a symfony2 controller that is returning 500, with this log entry:

[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将其部署到生产服务器时,才会出现此错误。但是,在同一控制器下定义的所有其他路由均正常工作。只有这一新的失败。这是一条可行的路线:

What's strange is everything is working properly, both in dev and prod modes, on my local test server. It is only when I try to deploy this to the production server using capifony that I get this error. However, all the other routes defined under the same controller are working properly. Only this new one fails. Here is a working route:

/**
 * 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 / sponsored到/ search / direct_sponsored),但在新路径下我仍然收到相同的500错误。 (当然,错误中有新的路径。)

I've tried changing the route (from /search/direct/sponsored to /search/direct_sponsored), but I still received the same 500 error at the new path. (With the new path in the error, of course.)

除了我在尝试尝试方面还很受限制,还没有深入研究Symfony和Sensio代码以跟踪其如何协调这些注释。大概这与安装到服务器有关,因为它在本地工作,但是据我所知,一切都应该相同。两者都使用composer来安装依赖项,因此所有供应商代码都应该相同。我们不会在服务器的发行版之间共享缓存,因此它可以使用全新的缓存。 (Capifony确实调用了应用程序/控制台缓存:warmup --env = prod。)

Beyond that I'm sort of stuck as far as what to try, short of digging into the guts of the Symfony and Sensio code to trace how its reconciling these annotations. Presumably this has something to do with installing to the server, since it works locally, but as far as I can tell, everything should be the same. Both use composer to install dependencies, so all the vendor code should be identical. We don't share a cache between releases to the server, so it's working with a fresh cache. (Capifony does call app/console cache:warmup --env=prod.)

这听起来通常是由于路由yml中的控制器规范不匹配导致的Action函数的名称,或者该函数不公开。

It sounds like usually this error is due to the controller specification in the routing yml not matching the name of the Action function, or alternately the function not being public. Neither applies here.

我很高兴提供所要求的任何其他信息。

I'm happy to provide any additional information requested.

编辑:现在正在工作,尽管我什么都没改变。我认为这与Capifony的多阶段扩展有关。我们正在运行三个阶段(开发,测试版,产品)。我曾在开发阶段对此进行测试,但一时兴起,我尝试将其部署到其他阶段以查看是否会有任何不同。起初并没有,但是在我将这三个都部署完之后,当我重新部署到其中任何一个时,路由就开始起作用了。

It's working now, although I haven't changed anything. I think what's going on has to do with Capifony's multistage extension. We are running three stages (development, beta, prod). I had been testing this on the dev stage, but on a whim I tried deploying it to the other stages to see if that would make any difference. It didn't at first, but after I had deployed to all three, when I then re-deployed to any one of them, the route started working.

编辑2 :多阶段是大多数问题,但还有更多。

Edit 2: Multistage was most of the problem, but there was more to it. See my answer below.

推荐答案

原来,问题出在ApcClassLoader。 app.php中的这两行指示sf2使用APC来缓存应用程序使用的各种类的位置(文件系统路径):

It turns out the problem was due to the ApcClassLoader. These two lines in app.php instruct sf2 to use APC to cache the locations (filesystem paths) of various classes used by the application:

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

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

You're supposed to change the sf2 to a unique prefix to avoid cache key conflicts. We did that, but used the same 'unique' prefix for each of our stages, which meant that when we ran a deployment and cleared the apc cache, whichever stage was accessed first would set the file locations in the cache, and those same files would then be used for all stages. Since it's a busy site, this meant the production stage files ended up being used for the other stages.

解决方案应该是简单地部署单独版本的app.php。每个阶段都有一个单独的前缀。 (或者为前缀传递一个变量;但是您想这样做。)但是,我还发现,即使我们清除了APC缓存,[[同此处所述, ] [1])。我目前无法解释为什么会发生这种情况,因为即使我们在清除之前添加了延迟,以防万一正在处理任何请求,这种情况似乎也会发生。

The solution should be to simply deploy a separate version of app.php for each stage, with a separate prefix. (Or pass in a variable for the prefix; however you want to do it.) However, I also found that very occasionally the previous release of the same stage was polluting the cache, even though we clear the APC cache ([as described here][1]) immediately after deploying. I can't currently explain why that happens, since it seems to happen even if we add a delay before clearing, in case any requests are in progress.

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

So for now, we're simply going to use composer instead of apc to save the class map, as described in the "Use Composer's Class Map Functionality" section here: http://symfony.com/doc/current/book/performance.html

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

Ah, and this explains the last bit, how the earlier releases were polluting the cache even after the new ones were released: https://stackoverflow.com/a/23419954/160565. We use symlinks for deployment, and PHP was caching the old symlink routes, causing the previous deployment to refill the cache before the symlink was updated. The answer linked there explains how to work around that.

这篇关于URI的控制器无法使用注释进行调用的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆