AbstractConnection.php 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218
  1. <?php
  2. /*
  3. * This file is part of the Predis package.
  4. *
  5. * (c) Daniele Alessandri <suppakilla@gmail.com>
  6. *
  7. * For the full copyright and license information, please view the LICENSE
  8. * file that was distributed with this source code.
  9. */
  10. namespace Predis\Connection;
  11. use InvalidArgumentException;
  12. use Predis\CommunicationException;
  13. use Predis\Command\CommandInterface;
  14. use Predis\Protocol\ProtocolException;
  15. /**
  16. * Base class with the common logic used by connection classes to communicate
  17. * with Redis.
  18. *
  19. * @author Daniele Alessandri <suppakilla@gmail.com>
  20. */
  21. abstract class AbstractConnection implements SingleConnectionInterface
  22. {
  23. private $resource;
  24. private $cachedId;
  25. protected $parameters;
  26. protected $initCommands = array();
  27. /**
  28. * @param ParametersInterface $parameters Initialization parameters for the connection.
  29. */
  30. public function __construct(ParametersInterface $parameters)
  31. {
  32. $this->parameters = $this->assertParameters($parameters);
  33. }
  34. /**
  35. * Disconnects from the server and destroys the underlying resource when
  36. * PHP's garbage collector kicks in.
  37. */
  38. public function __destruct()
  39. {
  40. $this->disconnect();
  41. }
  42. /**
  43. * Checks some of the parameters used to initialize the connection.
  44. *
  45. * @param ParametersInterface $parameters Initialization parameters for the connection.
  46. * @return ParametersInterface
  47. */
  48. protected function assertParameters(ParametersInterface $parameters)
  49. {
  50. $scheme = $parameters->scheme;
  51. if ($scheme !== 'tcp' && $scheme !== 'unix') {
  52. throw new InvalidArgumentException("Invalid scheme: '$scheme'.");
  53. }
  54. if ($scheme === 'unix' && !isset($parameters->path)) {
  55. throw new InvalidArgumentException('Missing UNIX domain socket path.');
  56. }
  57. return $parameters;
  58. }
  59. /**
  60. * Creates the underlying resource used to communicate with Redis.
  61. *
  62. * @return mixed
  63. */
  64. abstract protected function createResource();
  65. /**
  66. * {@inheritdoc}
  67. */
  68. public function isConnected()
  69. {
  70. return isset($this->resource);
  71. }
  72. /**
  73. * {@inheritdoc}
  74. */
  75. public function connect()
  76. {
  77. if (!$this->isConnected()) {
  78. $this->resource = $this->createResource();
  79. return true;
  80. }
  81. return false;
  82. }
  83. /**
  84. * {@inheritdoc}
  85. */
  86. public function disconnect()
  87. {
  88. unset($this->resource);
  89. }
  90. /**
  91. * {@inheritdoc}
  92. */
  93. public function addConnectCommand(CommandInterface $command)
  94. {
  95. $this->initCommands[] = $command;
  96. }
  97. /**
  98. * {@inheritdoc}
  99. */
  100. public function executeCommand(CommandInterface $command)
  101. {
  102. $this->writeRequest($command);
  103. return $this->readResponse($command);
  104. }
  105. /**
  106. * {@inheritdoc}
  107. */
  108. public function readResponse(CommandInterface $command)
  109. {
  110. return $this->read();
  111. }
  112. /**
  113. * Helper method to handle connection errors.
  114. *
  115. * @param string $message Error message.
  116. * @param int $code Error code.
  117. */
  118. protected function onConnectionError($message, $code = null)
  119. {
  120. CommunicationException::handle(
  121. new ConnectionException(
  122. $this, "$message [{$this->parameters->scheme}://{$this->getIdentifier()}]", $code
  123. )
  124. );
  125. }
  126. /**
  127. * Helper method to handle protocol errors.
  128. *
  129. * @param string $message Error message.
  130. */
  131. protected function onProtocolError($message)
  132. {
  133. CommunicationException::handle(
  134. new ProtocolException(
  135. $this, "$message [{$this->parameters->scheme}://{$this->getIdentifier()}]"
  136. )
  137. );
  138. }
  139. /**
  140. * {@inheritdoc}
  141. */
  142. public function getResource()
  143. {
  144. if (isset($this->resource)) {
  145. return $this->resource;
  146. }
  147. $this->connect();
  148. return $this->resource;
  149. }
  150. /**
  151. * {@inheritdoc}
  152. */
  153. public function getParameters()
  154. {
  155. return $this->parameters;
  156. }
  157. /**
  158. * Gets an identifier for the connection.
  159. *
  160. * @return string
  161. */
  162. protected function getIdentifier()
  163. {
  164. if ($this->parameters->scheme === 'unix') {
  165. return $this->parameters->path;
  166. }
  167. return "{$this->parameters->host}:{$this->parameters->port}";
  168. }
  169. /**
  170. * {@inheritdoc}
  171. */
  172. public function __toString()
  173. {
  174. if (!isset($this->cachedId)) {
  175. $this->cachedId = $this->getIdentifier();
  176. }
  177. return $this->cachedId;
  178. }
  179. /**
  180. * {@inheritdoc}
  181. */
  182. public function __sleep()
  183. {
  184. return array('parameters', 'initCommands');
  185. }
  186. }