<?php<liu21st@gmail.com>declare (strict_types = 1);
namespace think\cache\driver;
use think\cache\Driver;
class Memcached extends Driver
{
protected $options = [
'host' => '127.0.0.1',
'port' => 11211,
'expire' => 0,
'timeout' => 0, 'prefix' => '',
'username' => '', 'password' => '', 'option' => [],
'tag_prefix' => 'tag:',
'serialize' => [],
];
public function __construct(array $options = [])
{
if (!extension_loaded('memcached')) {
throw new \BadFunctionCallException('not support: memcached');
}
if (!empty($options)) {
$this->options = array_merge($this->options, $options);
}
$this->handler = new \Memcached;
if (!empty($this->options['option'])) {
$this->handler->setOptions($this->options['option']);
}
if ($this->options['timeout'] > 0) {
$this->handler->setOption(\Memcached::OPT_CONNECT_TIMEOUT, $this->options['timeout']);
}
$hosts = (array) $this->options['host'];
$ports = (array) $this->options['port'];
if (empty($ports[0])) {
$ports[0] = 11211;
}
$servers = [];
foreach ($hosts as $i => $host) {
$servers[] = [$host, $ports[$i] ?? $ports[0], 1];
}
$this->handler->addServers($servers);
if ('' != $this->options['username']) {
$this->handler->setOption(\Memcached::OPT_BINARY_PROTOCOL, true);
$this->handler->setSaslAuthData($this->options['username'], $this->options['password']);
}
}
public function has($name): bool
{
$key = $this->getCacheKey($name);
return $this->handler->get($key) ? true : false;
}
public function get($name, $default = null)
{
$this->readTimes++;
$result = $this->handler->get($this->getCacheKey($name));
return false !== $result ? $this->unserialize($result) : $default;
}
public function set($name, $value, $expire = null): bool
{
$this->writeTimes++;
if (is_null($expire)) {
$expire = $this->options['expire'];
}
$key = $this->getCacheKey($name);
$expire = $this->getExpireTime($expire);
$value = $this->serialize($value);
if ($this->handler->set($key, $value, $expire)) {
return true;
}
return false;
}
public function inc(string $name, int $step = 1)
{
$this->writeTimes++;
$key = $this->getCacheKey($name);
if ($this->handler->get($key)) {
return $this->handler->increment($key, $step);
}
return $this->handler->set($key, $step);
}
public function dec(string $name, int $step = 1)
{
$this->writeTimes++;
$key = $this->getCacheKey($name);
$value = $this->handler->get($key) - $step;
$res = $this->handler->set($key, $value);
return !$res ? false : $value;
}
public function delete($name, $ttl = false): bool
{
$this->writeTimes++;
$key = $this->getCacheKey($name);
return false === $ttl ?
$this->handler->delete($key) :
$this->handler->delete($key, $ttl);
}
public function clear(): bool
{
$this->writeTimes++;
return $this->handler->flush();
}
public function clearTag(array $keys): void
{
$this->handler->deleteMulti($keys);
}
}