Элементы кеша доступа, созданные вне Symfony, заставляют их работать только иногда, почему?

Я интегрирую устаревшее приложение Zend Framework 1 (ZF1) и приложение Symfony 3.2.6 (SF). Вкратце, как это работает:

  • Управление сеансом, страница входа (уникальная точка входа) и многое другое управляется приложением ZF1 и самим ZF1.
  • Нет вызова какого-либо контроллера Zend, шаблонов, помощников или чего-либо еще со стороны SF

Например: - http://localhost/login => будет управляться ZF1 - http://localhost/sf/quote => будет управляться SF (ключ /sf/ в URL)

Это означает, что у меня есть правило в Apache VH, говорящее: каждый запрос с /sf/* в URL-адресе отправляет его на app.php|app_dev.php, который является Symfony, иначе он обойдёт это правило и перейдёт напрямую к ZF1.

Имея это первое, что я делаю, это вхожу в приложение, используя устаревшее приложение ZF1. После успешного входа в систему я перенаправляюсь на панель инструментов, и NavigationController.php вызывается из макета main.phtml, используя следующий код: $this->action('buildallmenu', 'navigation');.

В таком коде меню создается из БД, а затем, используя приведенный ниже код, я пытаюсь его кэшировать, поскольку мне это не нужно, и я не хочу снова обращаться к БД ни из ZF1, ни из SF.

use Predis\Client;
use Symfony\Component\Cache\Adapter\RedisAdapter;

$cached_items = [
    'main_nav'   => $main_nav,
    'sub_nav'    => $sub_nav,
    'footer_nav' => $footer_nav,
    'view_as'    => $view_as,
];

$redisConnection = new Client('tcp://cache_server:6379');
$cache           = new RedisAdapter($redisConnection);
$menu            = $cache->getItem('mmi_menus_'.session_id());

if (!$menu->isHit()) {
    $menu->set($cached_items);
    $cache->save($menu);
}

return $menu->get();

Почему session_id(), потому что меню является уникальным для каждого пользователя, поэтому имеет смысл добавить session_id() к элементу кэша Redis.

Оттуда я вижу переменную $cached_items, заполненную правильным содержимым, и она сохраняется в Redis.

Теперь я получаю доступ к контроллеру Symfony так, как я объяснял ранее: «путем доступа к URL-адресу». Допустим, я назвал URL-адрес следующим образом: http://localhost/sf/quote это выполнит правило и перенаправит на app_dev.php, что означает, что я сейчас на Symfony.

Первое, что я сделал, это проверил session_id() (распечатав значение session_id()) и сравнил со значением, созданным ZF1, и они совпадают.

Базовый шаблон SF вызывает контроллер как: {{ render(controller('CommonBundle:Setup:GenerateMenuItems')) }}. Это содержимое функции, вызываемой из шаблона:

public function GenerateMenuItemsAction()
{
    $menu = $this->get('mmi_pool')->getItem('mmi_menus_'.session_id());

    dump('mmi_menus_'.session_id());

    if ($menu->isHit()) {
        return $this->render(
            'CommonBundle:Layout:menu.html.twig',
            ['menu' => $menu->get()]
        );
    }

    return new  Response();
}

mmi_pool — это служба, определение которой выглядит следующим образом:

mmi_pool:
    parent: cache.adapter.redis
    tags:
      - name: cache.pool
        namespace: ''

Как настроен кеш на config.yml?

framework:
    cache:
        default_redis_provider:  redis://%redis_host%:%redis_port%

Обновить

Я обнаружил, что при первом входе в систему этот фрагмент кода не выполняется:

if (!$menu->isHit()) {
    $menu->set($cached_items);
    $cache->save($menu);
}

Я не уверен, почему. Это приводит к тому, что кеш хранит неправильные элементы и, следовательно, показывает неправильные элементы в SF.

что я делаю неправильно здесь? Я знаю, что кэширование сложное, но я определенно что-то здесь упускаю.


person ReynierPM    schedule 13.03.2017    source источник
comment
Я бы повторял ключ, который вы создаете, с обеих сторон, а также искал их после сохранения кеша внутри самого Redis. Видеть, что именно происходит, а не то, что, по вашему мнению, происходит, часто бывает поучительно.   -  person Alister Bulman    schedule 14.03.2017
comment
Используйте redis-cli, чтобы сделать запрос ключей *, а затем получить запрос для любого ключа, чтобы убедиться, что он хранится. Где вы переводите значение хранилища в объект?   -  person Carlos    schedule 14.03.2017
comment
@AlisterBulman Я добавил такую ​​информацию, но, как вы видите, на стороне Symfony ничего не отображается.   -  person ReynierPM    schedule 14.03.2017
comment
@Карлос, мне нужно перевести их в объект? Зачем? Я отправляю массив, я ожидаю получить массив :-\ я теряюсь в этом   -  person ReynierPM    schedule 14.03.2017
comment
Я обычно храню как $redis-›save('key',json_endode($vaue)); и получить json_decode($redis-›getItem('key'); поэтому он работает с любым типом данных.   -  person Carlos    schedule 14.03.2017
comment
Вы уверены, что session_id() одинакова в Symfony и Zend?   -  person malcolm    schedule 14.03.2017
comment
@malcolm да, я вижу информацию об отладке, которую я опубликовал   -  person ReynierPM    schedule 14.03.2017


Ответы (1)


Первый раз $menu это null, но всегда null из-за этого кода: if (!$menu->isHit()) { return ... Вы выходите из контроллера с оператором return.

if (!$menu->isHit()) {
    $menu->set($cached_items);
    $cache->save($menu);
}

return $menu->get();
person malcolm    schedule 13.03.2017