2013-12-23 3 views
0

У меня есть приложение CakePHP, размещенное на AWS Elastic Beanstalk. Из-за нескольких экземпляров EC2, которые я буду использовать в будущем, я хочу сохранить свои сеансы PHP в базе данных. AWS предоставляет очень хорошую библиотеку для хранения PHP-сессий в базе данных DynamoDB. См http://goo.gl/URoi3sCakePHP: Используйте обработчик сеанса DynamoDB AWS

Теперь я гнал на AWS SDK в папку мои поставщики и создали обертку доступа к нему (а плагин):

<?php 

Configure::load('aws'); 

require_once VENDORS . 'autoload.php'; 
use Aws\Common\Aws; 

class AwsComponent extends Component 
{ 
    private $_aws; 

    public function __construct() 
    { 
     $this->_aws = Aws::factory(array(
      'key' => Configure::read('Aws.key'), 
      'secret' => Configure::read('Aws.secret'), 
      'region' => Configure::read('Aws.region') 
     )); 
    } 

    public function getClient($service) 
    { 
     return $this->_aws->get($service); 
    } 
} 

Обертка работает хорошо, я уже реализованы некоторые S3 вещи. Теперь для обработчика сеанса я добавил следующий код на AppController.php:

public $components = array('Aws.Aws'); 

public function beforeFilter() 
{ 
    $this->_setSessionStorage(); 
} 

private function _setSessionStorage() 
{ 
    $client = $this->Aws->getClient('dynamodb'); 

    $client->registerSessionHandler(array(
     'table_name' => 'sessions' 
    )); 
} 

внутренний registerSessionHandler АМС (в) выполняется (тестировал), но сессия не неоспоримым хранится в таблице DynamoDB. Конечно, я создал таблицу раньше, и если я добавлю вызов в библиотеку AWS прямо к моему webroot/index.php, перед загрузкой диспетчера все будет работать нормально.

Я думаю, проблема в том, что мой код выполняется после вызова CakePHP session_start(). Итак, каков наилучший способ реализовать это? http://goo.gl/kUFUIR не помогает мне, я не хочу переписывать библиотеку AWS для совместимости с интерфейсом CakePHP.

ответ

2

Так что это лучший способ реализовать это? http://goo.gl/kUFUIR не помогает мне, я не хочу переписывать библиотеку AWS для beeing , совместимую с интерфейсом CakePHP.

Это на самом деле лучший способ. И это не означает, что изобретать колесо, абстракция в ООП означает, что вы делаете вещи доступными в общем интерфейсе, который можно заменить чем-то другим. Вы переносите внешний API или код в API, совместимый с вашей системой, в этом случае - приложение CakePHP.

Оберните вендора поставщика в адаптер AwsSession, который реализует CakeSessionHandlerInterface. Таким образом, API совместим с другими адаптерами сеанса в случае его изменения, и это может решить даже вашу основную проблему, потому что CakeSession позаботится об инициализации.

Ваш компонент инициализируется после сеанса в CakePHP, когда контроллер уже создан и затем инициализирует все его компоненты. Так что это происходит довольно поздно. Ваша альтернатива заключается в том, чтобы остановить CakePHP от инициализации сеанса, мне никогда не приходилось это делать, поэтому нет идеи, не глядя сама. Копайте в CakeSession. Даже если вам удастся это сделать, другие компоненты, такие как адаптер Auth по умолчанию, зависят от возможности работать с сеансами, поэтому вам необходимо позаботиться о том, что ваш компонент должен быть загружен до Auth. Довольно хрупкая система с множеством возможных точек отказа. Серьезно, пойдите для адаптера сеанса, угадайте его гораздо менее болезненным, чтобы заставить его работать таким образом.

При взгляде на документацию сеанса DynamoDB это кажется довольно простым. Расширьте обычный обработчик сеанса и перегрузите его только коллекцию init и мусора, чтобы добавить туда API-интерфейсы Aws, не гарантируя, что это правильно, но, похоже, легко.

+0

ОК спасибо, если это единственный способ, я дам ему попробовать. – iscon

1

То, что я в конечном итоге в CakePHP 3.

Src/Сеть/Session/DynamoDbSession.PHP

 
<?php 

namespace App\Network\Session; 

use Aws\DynamoDb\DynamoDbClient; 
use Cake\Core\Configure; 

class DynamoDbSession implements \SessionHandlerInterface 
{ 

    private $handler; 

    /** 
    * DynamoDbSession constructor. 
    */ 
    public function __construct() 
    { 
     $client = new DynamoDbClient(Configure::read('DynamoDbCredentials')); 

     $this->handler = $client->registerSessionHandler(array(
      'table_name' => Configure::read('DynamoDbCredentials.session_table') 
     )); 
    } 

    public function close() 
    { 
     return $this->handler->close(); 
    } 

    public function destroy($session_id) 
    { 
     return $this->handler->destroy($session_id); 
    } 

    public function gc($maxlifetime) 
    { 
     return $this->handler->gc($maxlifetime); 
    } 

    public function open($save_path, $session_id) 
    { 
     return $this->handler->open($save_path, $session_id); 
    } 

    public function read($session_id) 
    { 
     return $this->handler->read($session_id); 
    } 

    public function write($session_id, $session_data) 
    { 
     return $this->handler->write($session_id, $session_data); 
    } 

} 

Включите его в конфигурационном файле/app.php:

 
'Session' => [ 
     'defaults' => 'php', 
     'handler' => [ 
      'engine' => 'DynamoDbSession' 
     ], 
     'timeout' => (30 * 24 * 60) 
] 
Смежные вопросы