Контроллер для URI не вызывается, используя аннотации

У меня есть контроллер Symfony2, который возвращает 500, с этой записи журнала:

[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/ спонсорский на /search/direct_sponsored), но я все равно получил ту же ошибку 500 на новом пути. (С новым путем в ошибке, конечно.)

Кроме того, я как бы застрял в том, что нужно попробовать, если не копаться в кишечнике кода Symfony и Sensio, чтобы проследить, как он согласовывает эти аннотации. Предположительно, это как-то связано с установкой на сервер, поскольку он работает локально, но, насколько я могу судить, все должно быть одинаково. Оба используют composer для установки зависимостей, поэтому весь код поставщика должен быть одинаковым. Мы не разделяем кеш между выпусками на сервер, поэтому он работает с новым кешем. (Capifony вызывает кэш приложения / консоли:warmup --env=prod.)

Похоже, что обычно эта ошибка происходит из-за того, что спецификация контроллера в yml маршрутизации не соответствует названию функции Action или, наоборот, функция не является общедоступной. Ни то, ни другое здесь не применимо.

Я рад предоставить любую дополнительную запрашиваемую информацию.

Изменить: сейчас работает, хотя я ничего не изменил. Я думаю, что происходит с многоступенчатым расширением Capifony. Мы работаем в три этапа (разработка, бета, прод). Я проверял это на этапе разработки, но по какой-то причине попытался развернуть его на других этапах, чтобы увидеть, будет ли это иметь какое-то значение. Сначала этого не произошло, но после того, как я развернулся на всех трех, когда я затем развернул на любом из них, маршрут начал работать.

Редактировать 2: Многоступенчатая была большая часть проблемы, но это было еще не все. Смотрите мой ответ ниже.

1 ответ

Решение

Оказывается, проблема была из-за ApcClassLoader. Эти две строки в app.php инструктируют sf2 использовать APC для кэширования расположений (путей файловой системы) различных классов, используемых приложением:

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

Вы должны изменить sf2 на уникальный префикс, чтобы избежать конфликтов ключей кеша. Мы сделали это, но использовали один и тот же "уникальный" префикс для каждого из наших этапов, что означало, что когда мы запускаем развертывание и очищаем кэш-память apc, то на любом из этапов, к которому был получен доступ первым, будут заданы местоположения файлов в кэше и те же файлы. будет использоваться для всех этапов. Поскольку это загруженный сайт, это означало, что файлы рабочих этапов использовались для других этапов.

Решение должно состоять в том, чтобы просто развернуть отдельную версию app.php для каждого этапа с отдельным префиксом. (Или передайте переменную для префикса; как бы вы этого не хотели.) Однако я также обнаружил, что очень редко предыдущая версия того же этапа загрязняла кэш, даже если мы очищаем кэш APC ([как описано здесь). ][1]) сразу после развертывания. В настоящее время я не могу объяснить, почему это происходит, поскольку, похоже, это происходит, даже если мы добавляем задержку перед очисткой, если какие-либо запросы выполняются.

Поэтому сейчас мы просто собираемся использовать composer вместо apc для сохранения карты классов, как описано в разделе "Использование функциональности карты классов Composer" здесь: http://symfony.com/doc/current/book/performance.html

Изменить: Ах, и это объясняет последний момент, как более ранние выпуски загрязняли кеш даже после выпуска новых: /questions/23915256/simvolyi-capistrano-kotoryie-keshiruyutsya/23915265#23915265. Мы используем символические ссылки для развертывания, а PHP кэшировал старые маршруты символических ссылок, в результате чего предыдущее развертывание заполняло кэш до обновления символической ссылки. Ответ, связанный там, объясняет, как обойти это.

Другие вопросы по тегам