我在AWS Elastic Beanstalk上托管了一个CakePHP应用程序。由于我将来会使用多个EC2实例,我想将我的PHP会话存储在数据库中。 AWS提供了一个非常好的库,用于在其DynamoDB数据库中存储PHP会话。见http://goo.gl/URoi3s
现在我将AWS SDK放在我的vendor文件夹中并为它创建了一个访问包装器(一个插件):
<?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'
));
}
AWS的内部registerSessionHandler()被执行(测试它),但会话没有被存储到DynamoDB表中。当然我之前创建了这个表,如果我在加载调度程序之前将对AWS库的调用直接添加到我的webroot / index.php,一切正常。
我认为问题是我的代码是在CakePHP调用session_start()之后执行的。那么实现它的最佳方法是什么? http://goo.gl/kUFUIR对我没有帮助,我不想重写AWS库以便与CakePHP接口兼容。
答案 0 :(得分:2)
那么实现它的最佳方法是什么? http://goo.gl/kUFUIR 没有帮助我,我不想重写AWS库以供应用 与CakePHP接口兼容。
这实际上是最好的方法。这并不意味着重新发明轮子,OOP中的抽象意味着您可以在通用界面中提供可以用其他东西替换的东西。将外部API或代码包装在与系统兼容的API中,在本例中为CakePHP应用程序。
将供应商lib包装在实现CakeSessionHandlerInterface的AwsSession适配器中。这样,在您更改它的情况下,它的API与其他会话适配器兼容,甚至可能解决您的核心问题,因为CakeSession将负责初始化。
您的组件在CakePHP中的会话之后初始化,此时控制器已经实例化,然后正在初始化其所有组件。所以这发生在很晚的时候。你的替代方案是阻止CakePHP初始化会话,我从来没有必要这样做,所以不知道自己没有查找它。挖掘CakeSession。即使您设法这样做,其他组件(如默认的Auth适配器)依赖于能够使用Sessions,因此您必须处理在Auth之前必须加载组件的问题。相当脆弱的系统,有很多可能的失败点。说真的,转到Session适配器,猜测它以这种方式工作的痛苦要小得多。
通过快速查看DynamoDB Session文档,这似乎非常简单。扩展常规会话处理程序并仅重载它的init和garbage集合以在那里添加Aws API调用,不保证这是正确的但似乎很容易。
答案 1 :(得分:1)
我在CakePHP 3中最终得到了什么。
<强> SRC /网络/会话/ 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); } }
在config / app.php文件中激活它:
'Session' => [ 'defaults' => 'php', 'handler' => [ 'engine' => 'DynamoDbSession' ], 'timeout' => (30 * 24 * 60) ]