StandardSessionConnection.php 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149
  1. <?php
  2. namespace Aws\DynamoDb;
  3. use Aws\DynamoDb\Exception\DynamoDbException;
  4. /**
  5. * The standard connection performs the read and write operations to DynamoDB.
  6. */
  7. class StandardSessionConnection implements SessionConnectionInterface
  8. {
  9. /** @var DynamoDbClient The DynamoDB client */
  10. protected $client;
  11. /** @var array The session handler config options */
  12. protected $config;
  13. /**
  14. * @param DynamoDbClient $client DynamoDB client
  15. * @param array $config Session handler config
  16. */
  17. public function __construct(DynamoDbClient $client, array $config = [])
  18. {
  19. $this->client = $client;
  20. $this->config = $config + [
  21. 'table_name' => 'sessions',
  22. 'hash_key' => 'id',
  23. 'session_lifetime' => (int) ini_get('session.gc_maxlifetime'),
  24. 'consistent_read' => true,
  25. 'batch_config' => [],
  26. ];
  27. }
  28. public function read($id)
  29. {
  30. $item = [];
  31. try {
  32. // Execute a GetItem command to retrieve the item.
  33. $result = $this->client->getItem([
  34. 'TableName' => $this->config['table_name'],
  35. 'Key' => $this->formatKey($id),
  36. 'ConsistentRead' => (bool) $this->config['consistent_read'],
  37. ]);
  38. // Get the item values
  39. $result = isset($result['Item']) ? $result['Item'] : [];
  40. foreach ($result as $key => $value) {
  41. $item[$key] = current($value);
  42. }
  43. } catch (DynamoDbException $e) {
  44. // Could not retrieve item, so return nothing.
  45. }
  46. return $item;
  47. }
  48. public function write($id, $data, $isChanged)
  49. {
  50. // Prepare the attributes
  51. $expires = time() + $this->config['session_lifetime'];
  52. $attributes = [
  53. 'expires' => ['Value' => ['N' => (string) $expires]],
  54. 'lock' => ['Action' => 'DELETE'],
  55. ];
  56. if ($isChanged) {
  57. if ($data != '') {
  58. $attributes['data'] = ['Value' => ['S' => $data]];
  59. } else {
  60. $attributes['data'] = ['Action' => 'DELETE'];
  61. }
  62. }
  63. // Perform the UpdateItem command
  64. try {
  65. return (bool) $this->client->updateItem([
  66. 'TableName' => $this->config['table_name'],
  67. 'Key' => $this->formatKey($id),
  68. 'AttributeUpdates' => $attributes,
  69. ]);
  70. } catch (DynamoDbException $e) {
  71. return $this->triggerError("Error writing session $id: {$e->getMessage()}");
  72. }
  73. }
  74. public function delete($id)
  75. {
  76. try {
  77. return (bool) $this->client->deleteItem([
  78. 'TableName' => $this->config['table_name'],
  79. 'Key' => $this->formatKey($id),
  80. ]);
  81. } catch (DynamoDbException $e) {
  82. return $this->triggerError("Error deleting session $id: {$e->getMessage()}");
  83. }
  84. }
  85. public function deleteExpired()
  86. {
  87. // Create a Scan iterator for finding expired session items
  88. $scan = $this->client->getPaginator('Scan', [
  89. 'TableName' => $this->config['table_name'],
  90. 'AttributesToGet' => [$this->config['hash_key']],
  91. 'ScanFilter' => [
  92. 'expires' => [
  93. 'ComparisonOperator' => 'LT',
  94. 'AttributeValueList' => [['N' => (string) time()]],
  95. ],
  96. 'lock' => [
  97. 'ComparisonOperator' => 'NULL',
  98. ]
  99. ],
  100. ]);
  101. // Create a WriteRequestBatch for deleting the expired items
  102. $batch = new WriteRequestBatch($this->client, $this->config['batch_config']);
  103. // Perform Scan and BatchWriteItem (delete) operations as needed
  104. foreach ($scan->search('Items') as $item) {
  105. $batch->delete(
  106. [$this->config['hash_key'] => $item[$this->config['hash_key']]],
  107. $this->config['table_name']
  108. );
  109. }
  110. // Delete any remaining items that were not auto-flushed
  111. $batch->flush();
  112. }
  113. /**
  114. * @param string $key
  115. *
  116. * @return array
  117. */
  118. protected function formatKey($key)
  119. {
  120. return [$this->config['hash_key'] => ['S' => $key]];
  121. }
  122. /**
  123. * @param string $error
  124. *
  125. * @return bool
  126. */
  127. protected function triggerError($error)
  128. {
  129. trigger_error($error, E_USER_WARNING);
  130. return false;
  131. }
  132. }