Страницы

Поиск по вопросам

понедельник, 3 июня 2019 г.

Yii2 CacheSession создает сессию в $_SESSION и в кеше одновременно

Случайно заметил такой нюанс при использования хранилища сессий в кеше ( в моем случае memcached ) Yii2 создает одновременно ее же и в массиве $_SESSION, хотя по логике не должен его использовать если в настройках указывается другое хранилище
Конфиг: ( пример - http://www.yiiframework.com/doc-2.0/yii-web-cachesession.html )
'cache' => [ 'class' => 'yii\caching\MemCache', 'useMemcached' => TRUE, 'servers' => [ [ 'host' => '******/.system/memcache/socket', 'port' => 11211, 'weight' => 64, ],
] ], 'session' => [ 'class' => 'yii\web\CacheSession', // 'cache' => 'cache', ],
Создание сессии:
$session = Yii::$app->session; $userDataStorage = [ 'id' => $this->id, 'name' => $this->name, 'settings' => json_decode($this->settings), ]; $session->set('user_data' , $userDataStorage);
Проверяем:
echo 'Yii session -> '; var_dump(Yii::$app->session->get('user_data') ); echo '-------------
'; echo 'Php session -> '; var_dump($_SESSION); echo '-------------
'; var_dump(ini_get('session.save_path'));
Видим:
Yii session -> array(4) { ["id"]=> int(1) ["name"]=> string(5) "admin" ["settings"]=> NULL } ------------- Php session -> array(3) { ["__flash"]=> array(0) { } ["__id"]=> int(1) ["user_data"]=> array(4) { ["id"]=> int(1) ["name"]=> string(5) "admin" ["settings"]=> NULL } }
------------- string(24) "****/.system/tmp"
Собственно это баг или... ? В чем тогда смысль настройки хранения сессий в кеше если он дублируется со стандартным ? Или я что-то делаю не так?
СОРРИ не доглядел. https://github.com/yiisoft/yii2/blob/master/framework/web/Session.php методом registerSessionHandler() устанавливает session_set_save_handler а класс "CacheSession" реализует методы которые будут хранить сессию в кеше определенном в настройках, т.о. $_SESSION хранится уже не в файле папки tmp (как по умолчанию) а в memcached. Вопрос закрыт.


Ответ

Возможно будет кому-то полезно, тогда начну сначала. Как настроить кеширование Yii2 для работы с memcache или memcached ( в чем отличия я думаю тут описывать нет смысла, в нете масса инфы по этому поводу ), постараюсь кратко изложить саму суть. Итак, для начала заходим в файл конфигурации проэкта и добавляем настройки кеширования и подключения к серверу
'components' => [
...
'cache' => [ 'class' => 'yii\caching\MemCache', 'useMemcached' => TRUE, 'servers' => [ [ 'host' => 'localhost', 'port' => 11211, 'weight' => 64, ],
] ],
... ]
Параметр 'useMemcached' ( класс MemCache расположен в директории yii2/caching/MemCache.php ( наследуется от компонента Cache /yii2/caching/Cache.php ) и по умолчанию FALSE, т.е. юзает memcache ) указывает на то что будет использоватся memcache или memcached, для использования memcached ставим в конфиге 'useMemcached' => TRUE Далее если все верно настроено прописано можем юзать кеш
\Yii::$app->cache->set('key', 'value'); \Yii::$app->cache->get('key');
//или можем кешировать запросы в БД
$db = Yii::$app->db; $result = $db->cache(function ($db) { return $db->createCommand('SELECT * FROM tablename LIMIT 0,1000')->queryAll(); }); // и т.д. ****
Подробнее в доке http://www.yiiframework.com/doc-2.0/guide-caching-data.html
Тут сразу нужно оговорится если вы захотите проверить работу Yii2 memcached напрямую, т.е.
в Yii2
\Yii::$app->cache->set('mykey', 'value');
в произвольном файле
$m = new Memcached(); $m->addServer('localhost', 11211); var_dump($m->get('mykey'));
У вас ничего не получится т.к. компонент Cache Yii ( /yii2/caching/Cache.php ) методом buildKey так сказать "нормализует" ключи ( описание метода есть в классе ), но можно для теста сделать так
в Yii2
$cache = Yii::$app->cache; $keyStr = 'cache_test'; $key = $cache->buildKey($keyStr); $cache->set($keyStr, 'This is mem test!'); $get = $cache->get($keyStr); var_dump($get , $key); // дампим результат из кеша и сгенерированный ключ ( копируем его )
в произвольном файле
$m = new Memcached(); $m->addServer('localhost', 11211); $result = $m->get('242c9254b0a4b5ea5c7f0e000f668408'); // Вставляем полученый ключ
var_dump(unserialize($result));
Далее собственно ближе к сути, мы хотим хранить сесии в нашем мемкеше, для этого идем обратно в конфиг и добавляем после настроек кеша следующее
'session' => [ 'class' => 'yii\web\CacheSession', //'cache' => 'cache', ],
Теперь для работы с сессией будет заюзан класс CacheSession ( /yii2/web/CacheSession.php наследуется от Session /yii2/web/Session.php ) и можно создать нашу сессию
\Yii::$app->session->set('Mysession', 'Mem session');
И собственно тут у меня возник некий конфуз, ибо
\Yii::$app->session->get('Mysession'); // Вернет нам значение сессии $_SESSION // К моему удивлению так же содержал в себе эту сессию
Но на самом деле ничего страшного здесь нет, $_SESSION уже не хранится на сервере в папке tmp как по умолчанию, теперь $_SESSION хранится в мемкешед.
Все дело в том что класс CacheSession переопределяет некоторые методы класса Session ( в подробности работы вдаватся не буду, можно впринципе пройтись по этим файлам и посмотреть ) в т.ч. getUseCustomStorage(), так же класс Session имеет метод registerSessionHandler() который вызывается при откритии сессии, метод open(), в Session и вызывает в этом случаи getUseCustomStorage() который был переопределен, собственно после этого и происходит магия переноса $_SESSION в мемкешед, функция session_set_save_handler() ( http://php.net/manual/ru/function.session-set-save-handler.php ) переопределит методы работы с сессией на пользовательские.
После этого если мы сделаем так $_SESSION['mysession'] = 'value' ( так же как и в методе Session set() ), после открытия сесиии медодом Session open(), сессия будет хранится в нашем кеше.
Надеюсь мои изысканя будут кому-то полезными

Комментариев нет:

Отправить комментарий