타사 모듈이나 다른 플러그인에 의존하지 않고이 문제를 해결하는 가장 간단한 방법은 Drupals 핵심 SessionHandler 클래스를 재정의하는 것입니다.
먼저 내 모듈에서 컨테이너에 내 SessionHandler 클래스 정의를 다시 정의하도록 지시하는 ServiceProvider 클래스를 만들었습니다. 요청 스택 만 생성자에 전달되도록 확실히하기 위해 데이터베이스 연결 서비스가 필요하지 않았습니다.
<?php
namespace Drupal\my_module;
use Drupal\Core\DependencyInjection\ContainerBuilder;
use Drupal\Core\DependencyInjection\ServiceProviderBase;
use Symfony\Component\DependencyInjection\Reference;
class OoAuthServiceProvider extends ServiceProviderBase
{
/**
* {@inheritdoc}
*/
public function alter(ContainerBuilder $container)
{
$container->getDefinition('session_handler.storage')
->setClass('Drupal\my_module\SessionHandler')
->setArguments([
new Reference('request_stack')
]);
}
}
나는 다음 내 자신의 레디 스 SessionHandler을 만들 진행하십시오 SessionHandler 내 자신의 구현에 사용
<?php
namespace Drupal\my_module;
use Drupal\Component\Utility\Crypt;
use Drupal\Core\DependencyInjection\DependencySerializationTrait;
use Drupal\Core\Utility\Error;
use Symfony\Component\HttpFoundation\RequestStack;
use Symfony\Component\HttpFoundation\Session\Storage\Proxy\AbstractProxy;
/**
* Default session handler.
*/
class SessionHandler extends AbstractProxy implements \SessionHandlerInterface {
use DependencySerializationTrait;
/**
* The request stack.
*
* @var RequestStack
*/
protected $requestStack;
/**
* @var \Redis
*/
protected $redis;
/**
* SessionHandler constructor.
*
* @param RequestStack $requestStack
*/
public function __construct(RequestStack $requestStack)
{
$this->requestStack = $requestStack;
// TODO: Store redis connection details in config.
$this->redis = (new PhpRedis())->getClient('redis-host', 6379);
}
/**
* {@inheritdoc}
*/
public function open($savePath, $name)
{
return true;
}
/**
* {@inheritdoc}
*/
public function read($sid)
{
$data = '';
if (!empty($sid)) {
$query = $this->redis->get(Crypt::hashBase64($sid));
$data = unserialize($query);
}
return (string) $data['session'];
}
/**
* {@inheritdoc}
*/
public function write($sid, $value)
{
// The exception handler is not active at this point, so we need to do it
// manually.
var_dump(['Value', $value]);
try {
$request = $this->requestStack->getCurrentRequest();
$fields = [
'uid' => $request->getSession()->get('uid', 0),
'hostname' => $request->getClientIP(),
'session' => $value,
'timestamp' => REQUEST_TIME,
];
$this->redis->set(
Crypt::hashBase64($sid),
serialize($fields),
(int) ini_get("session.gc_maxlifetime")
);
return true;
}
catch (\Exception $exception) {
require_once DRUPAL_ROOT . '/core/includes/errors.inc';
// If we are displaying errors, then do so with no possibility of a
// further uncaught exception being thrown.
if (error_displayable()) {
print '<h1>Uncaught exception thrown in session handler.</h1>';
print '<p>' . Error::renderExceptionSafe($exception) . '</p><hr />';
}
return true;
}
}
/**
* {@inheritdoc}
*/
public function close()
{
return true;
}
/**
* {@inheritdoc}
*/
public function destroy($sid)
{
// Delete session data.
$this->redis->delete(Crypt::hashBase64($sid));
return true;
}
/**
* {@inheritdoc}
*/
public function gc($lifetime)
{
// Redundant method when using Redis. You no longer have to check the session
// timestamp as the session.gc_maxlifetime is set as TTL on write.
return true;
}
}
PhpRedis은 레디 스 연결을 다루는 단지 작은 유틸리티 클래스입니다.
<?php
namespace Drupal\my_module;
/**
* Class PhpRedis
* @package Drupal\oo_auth
*/
class PhpRedis implements ClientInterface
{
/**
* {@inheritdoc}
*/
public function getClient($host = null, $port = null, $base = null, $password = null)
{
$client = new \Redis();
$client->connect($host, $port);
if (isset($password)) {
$client->auth($password);
}
if (isset($base)) {
$client->select($base);
}
// Do not allow PhpRedis serialize itself data, we are going to do it
// oneself. This will ensure less memory footprint on Redis size when
// we will attempt to store small values.
$client->setOption(\Redis::OPT_SERIALIZER, \Redis::SERIALIZER_NONE);
return $client;
}
/**
* {@inheritdoc}
*/
public function getName() {
return 'PhpRedis';
}
}
<?php
namespace Drupal\my_module;
/**
* Interface ClientInterface
* @package Drupal\oo_auth
*/
interface ClientInterface
{
/**
* Get the connected client instance.
*
* @param null $host
* @param null $port
* @param null $base
*
* @return mixed
*/
public function getClient($host = NULL, $port = NULL, $base = NULL);
/**
* Get underlying library name used.
*
* This can be useful for contribution code that may work with only some of
* the provided clients.
*
* @return string
*/
public function getName();
}
거기에 어떤 제안 설명서 (I 찾을 수) 당신 레디 스를 사용하는 방법의 예를 제공한다는 없다 (이 것 어떤 데이터 저장소와 사실 작업에서) 당신의 드루팔 설치를위한 세션 저장소로. 그것을 얻고 다른 제 3 자 모듈로 실행하는 방법에 대한 글이 있지만 괜찮지 만 나는 여분의 보풀을 원하지 않았다.
안녕하세요, 칼, 당신은 귀하의 모듈과 지퍼가 있으시겠습니까? Drupal 프로젝트에서 구현할 수 있는지보고 싶습니다. –
안녕하세요, André, 저는 이전 회사와 마찬가지로 불행하지 않습니다. 그러나 도움이 필요하시면 저에게 이메일을 보내 주시기 바랍니다. 그리고 최선을 다해 도와 드리겠습니다 : [email protected] :) – Kal