inner = new \Memcached(); if (!$this->inner->setOption(\Memcached::OPT_BINARY_PROTOCOL, true)) { $err = $this->inner->getResultMessage(); throw new \RuntimeException("Unable to set the memcached protocol: '$err'"); } if (!$this->inner->setOption(\Memcached::OPT_PREFIX_KEY, $prefix)) { $err = $this->inner->getResultMessage(); throw new \RuntimeException("Unable to set the memcached prefix: '$err'"); } $maybe_unix_path = self::asUnixSocketPath($server_uri); $is_unix = $maybe_unix_path !== null; if ($is_unix) { $server_uri = $maybe_unix_path; } // Memcached keeps the server connections open across requests. $current_servers = $this->inner->getServerList(); $found_in_curr = false; foreach ($current_servers as $curr) { // Ignore the port if the server is connected with a unix socket. if ($curr['host'] === $server_uri && ($is_unix || $curr['port'] === $server_port)) { $found_in_curr = true; } } if (!$found_in_curr) { if (!empty($current_servers)) { if (!$this->inner->resetServerList()) { $err = $this->inner->getResultMessage(); throw new \RuntimeException("Unable to reset the memcached server list: '$err'"); } } if (!$this->inner->addServer($server_uri, $server_port, $server_weight)) { $err = $this->inner->getResultMessage(); throw new \RuntimeException("Unable to add memcached servers: '$err'"); } } } public function get(string $key): mixed { $ret = $this->inner->get($key); // If the returned value is false but the retrival was a success, then the value stored was a boolean false. if ($ret === false && $this->inner->getResultCode() !== \Memcached::RES_SUCCESS) { return null; } return $ret; } public function set(string $key, mixed $value, mixed $expires = false): void { $this->inner->set($key, $value, (int)$expires); } public function delete(string $key): void { $this->inner->delete($key); } public function flush(): void { $this->inner->flush(); } }