php没有开启Memcache扩展类时
模拟PHP Memcache 类。
当服务器没有开启Memcache扩展的时候。可以采用本类
使用方法
class_exists('Memcache') or include './Memcache.class.php';
$mem = new Memcache;
$mem->add('key','value');
$mem->get('key')
目前已实现方法
Memcache::connect ( string $host [, int $port ] )
Memcache::get( string $key )
Memcache::add( string $key , mixed $var [, int $expire] )
Memcache::set( string $key , mixed $var [, int $expire] )
Memcache::replace( string $key , mixed $var [, int $expire] )
Memcache::getVersion( void )
Memcache::flush ( void )
Memcache::delete( string $key )
Memcache::close( void )
属性
Memcache::info 服务器相关信息 返回数组
注意 2014年3月28日
本类需要sockets支持
本类的 指定Memcache下标长度超出32字节。自动对key进行MD5
@Version Memcache.class.php 1.1 2014-3-29 04:10:18 $
bug 修复
1. 修复必须需要sockets扩展才能使用的缺陷
2. 代码优化
3. 添加手动关闭 连接方法
1 /** 2 * Created by Iyoule . 3 * 模拟PHP Memcache 类。 4 * 当服务器没有开启Memcache扩展的时候。可以采用本类 5 * 使用方法 6 * class_exists('Memcache') or include './Memcache.class.php'; 7 * $mem = new Memcache; 8 * $mem->add('key','value'); 9 * $mem->get('key') 10 * 目前已实现方法 11 * Memcache::connect ( string $host [, int $port ] ) 12 * Memcache::get( string $key ) 13 * Memcache::add( string $key , mixed $var [, int $expire] ) 14 * Memcache::set( string $key , mixed $var [, int $expire] ) 15 * Memcache::replace( string $key , mixed $var [, int $expire] ) 16 * Memcache::getVersion( void ) 17 * Memcache::flush ( void ) 18 * Memcache::delete( string $key ) 19 * Memcache::close( void ) 2014-3-29 02:13:19 20 * 21 * 属性 22 * Memcache::info 服务器相关信息 返回数组 23 * 24 * 注意 25 * 本类需要sockets支持 26 * 本类的 指定Memcache下标长度超出32字节。自动对key进行MD5 27 * 28 * @Version Memcache.class.php 1.1 2014-3-29 04:10:18 $ 29 * bug 修复 30 * 1. 修复必须需要sockets扩展才能使用的缺陷 31 * 2. 代码优化 32 * 3. 添加手动关闭 连接方法 33 * 34 * Email: 136045277#qq.com 群:220256148 35 * Version: Memcache.class.php 1.1 $ 36 * Time: 2014-3-28 上午12:04 37 */ 38 class Memcache 39 { 40 /** 41 * @var 服务器地址 42 */ 43 public $host; 44 45 /** 46 * @var 服务器端口 47 */ 48 public $port; 49 50 /** 51 * @var array memcache 服务信息 52 */ 53 private $info = array(); 54 55 /** 56 * @var null socket资源 57 */ 58 private $socket = null; 59 60 /** 61 * @var memcache 命令 62 */ 63 private $command; 64 65 /** 66 * @var int 连接超时时间 67 */ 68 private $connect_timeout = 30; 69 private $errno; 70 private $errstr; 71 72 /** 73 * @var mamcache保存数据时长 74 */ 75 private $expire; 76 77 /** 78 * @var memcache 保存数据的key 长于32位置将被MD5 79 */ 80 private $key; 81 82 /** 83 * @var memcache 保存的值 84 */ 85 private $var; 86 87 /** 88 * @var bool 主机是否关闭连接 89 */ 90 private $is_close = false; 91 92 /** 93 * @var string 连接函数 94 */ 95 private $connect_method; 96 97 /** 98 * 构造方法 判断 根据系统自动判断连接类型 99 * 优先级 100 * 优先 -> 低 101 * stream_socket_client -> fsockopen -> pfsockopen -> socket_create 102 */ 103 public function __construct() 104 { 105 if (function_exists('stream_socket_client')) { 106 $this->connect_method = 'stream_socket_client'; 107 } elseif (function_exists('fsockopen')) { 108 $this->connect_method = 'fsockopen'; 109 } elseif (function_exists('pfsockopen')) { 110 $this->connect_method = 'pfsockopen'; 111 } elseif (function_exists('socket_create')) { 112 $this->connect_method = 'socket_create'; 113 } 114 } 115 116 /** 117 * 从服务端检回一个元素 118 * 如果服务端之前有以key作为key存储的元素, Memcache::get()方法此时返回之前存储的值。 119 * 你可以给 Memcache::get()方法传递一个数组(多个key)来获取一个数组的元素值,返回的数组仅仅包含从 服务端查找到的key-value对。 120 * @param $key 要获取值的key或key数组。 121 * @return bool|string 返回key对应的存储元素的字符串值或者在失败或key未找到的时候返回FALSE。 122 * @lastTime 2014-3-28 02:44:00 123 */ 124 public function get($key) 125 { 126 $this->key = isset($key{32}) ? md5($key) : $key; 127 $command = "get $key\r\n"; 128 $this->socket_write($command); 129 do { 130 $out = $this->socket_read(128); 131 } while (strlen($out) == 1); 132 $list = preg_split("/\s/", $out); 133 if ($list[0] == 'END') return false; 134 $string = array(); 135 $runing = 0; 136 do { 137 $string[$runing] = $this->socket_read(128); 138 substr($string[$runing], 0, 3) == 'END' && strlen($string[$runing]) <= 5 ? $runing = false : $runing++; 139 } while ($runing !== false); 140 array_pop($string); 141 $string = join('', $string); 142 $indexOf = 0; 143 if ($this->connect_method == 'socket_create') { 144 $indexOf = 1; 145 } 146 $string = substr($string, $indexOf, -2); 147 return $string; 148 } 149 150 /** 151 * 建立连接 152 * @param $host memcache 服务器地址 153 * @param int $post 端口 154 * @lastTime 2014-3-28 02:40:09 155 */ 156 public function connect($host, $post = 11211) 157 { 158 $this->host = $host; 159 $this->port = $post; 160 $this->create_socket(); 161 $this->info(); 162 } 163 164 /** 165 * 魔法方法 构造 add set replace方法 166 * @param $method 167 * @param $args 168 * @return mixed 169 * @lastTime 2014-3-28 02:40:28 170 */ 171 public function __call($method, $args) 172 { 173 if (in_array($method, array('add', 'set', 'replace', 'delete'))) { 174 array_unshift($args, $method); 175 return call_user_func_array(array($this, 'set__'), $args); 176 } 177 } 178 179 /** 180 * 魔法方法 181 * @param $name 182 * @return array 183 * @lastTime 2014-3-29 04:17:17 184 */ 185 public function __get($name) 186 { 187 if($name=='info') 188 return $this->info; 189 } 190 191 /** 192 * 针对 魔法方法 add set replace方法进行的处理 193 * @param $func 方法名字 194 * @param $key memcache的key下标 195 * @param $var 设置的值 196 * @param int $expire memcache对数据的保存时间 默认24小时 197 * @return bool 198 * @lastTime 时间 199 */ 200 private function set__($func, $key, $var = null, $expire = 86400) 201 { 202 if ($this->is_close) 203 return false; 204 $this->command = trim($func); 205 $this->key = isset($key{32}) ? md5($key) : $key; 206 if ($func != 'delete') { 207 $this->var = trim($var); 208 $this->expire = trim($expire); 209 } 210 return $this->send_do(); 211 } 212 213 /** 214 * 清空memcache的值 215 * @return bool 216 * @lastTime 2014-3-28 02:43:23 217 */ 218 public function flush() 219 { 220 $command = "flush_all\r\n"; 221 $this->socket_write($command); 222 if ($this->socket_read(3) == 'OK') { 223 return true; 224 } 225 return false; 226 } 227 228 /** 229 * Memcache::getVersion — 返回服务器版本信息 230 * Memcache::getVersion()返回一个字符串表示的服务端版本号 231 * 同样你也可以使用 Memcache::info['version']。 232 * @return mixed 233 * @lastTime 2014-3-28 02:44:56 234 */ 235 public function getVersion() 236 { 237 return $this->info['version']; 238 } 239 240 /** 241 * 对 add set replace delete 方法进行的处理 242 * @return bool 243 * @lastTime 2014-3-28 02:45:55 244 */ 245 private function send_do() 246 { 247 if ($this->command != 'delete') { 248 $command = sprintf("%s %s 0 %d %d\r\n", $this->command, $this->key, $this->expire, strlen($this->var)); 249 $var = sprintf("%s\r\n", $this->var); 250 $this->socket_write($command); 251 $this->socket_write($var); 252 } else { 253 $command = sprintf("%s %s\r\n", $this->command, $this->key); 254 $this->socket_write($command); 255 } 256 do { 257 $result = $this->socket_read(64); 258 } while (strlen($result) == 1); 259 $result = str_replace(array("\r", "\n"), '', $result); 260 if (substr($result, 0, 5) == 'STORE' || substr($result, 0, 6) == 'DELETE') { 261 return true; 262 } 263 return false; 264 } 265 266 /** 267 * 创建连接类型 268 * @return bool 269 * @lastTime 2014-3-29 04:06:15 270 */ 271 private function create_socket() 272 { 273 $method = $this->connect_method; 274 if ($method) { 275 switch ($method) { 276 case 'socket_create': 277 $this->socket = socket_create(AF_INET, SOCK_STREAM, SOL_TCP); 278 socket_connect($this->socket, $this->host, $this->port); 279 break; 280 case 'fsockopen': 281 case 'pfsockopen': 282 $this->socket = $method($this->host, $this->port, $this->errno, $this->errstr, $this->connect_timeout); 283 break; 284 case 'stream_socket_client': 285 $address = sprintf("tcp://%s:%d", $this->host, $this->port); 286 $this->socket = $method($address, $this->errno, $this->errstr, $this->connect_timeout); 287 break; 288 } 289 } 290 if (is_resource($this->socket)) 291 return true; 292 } 293 294 /** 295 * 写入套字节 296 * @param $string 297 * @return int 298 * @lastTime 2014-3-28 02:46:40 299 */ 300 private function socket_write($string) 301 { 302 $return = false; 303 if ($this->connect_method == 'socket_create') 304 $return = socket_write($this->socket, $string, strlen($string)); 305 else if ($this->connect_method) 306 $return = fwrite($this->socket, $string); 307 return $return; 308 } 309 310 /** 311 * 读取套字节 312 * @param $len 取出的长度 313 * @return string 314 * @lastTime 2014-3-28 02:47:08 315 */ 316 private function socket_read($len) 317 { 318 $return = null; 319 if ($this->connect_method == 'socket_create') 320 $return = socket_read($this->socket, $len, PHP_NORMAL_READ); 321 else if ($this->connect_method) 322 $return = fgets($this->socket, $len); 323 return $return; 324 } 325 326 /** 327 * 服务器的信息处理 328 * @return array 329 * @lastTime 2014-3-28 02:47:46 330 */ 331 private function info() 332 { 333 if (!empty($this->info)) 334 return $this->info; 335 $this->socket_write("stats\r\n"); 336 $string = array(); 337 if ($this->connect_method) { 338 $runing = 0; 339 do { 340 $string[$runing] = $this->socket_read(68); 341 substr($string[$runing], 0, 3) == 'END' ? $runing = false : $runing++; 342 } while ($runing !== false); 343 $string = join("\r\n", $string); 344 $string = explode("\r\n", $string); 345 $string = array_filter($string, function ($value) { 346 return isset($value{4}); 347 }); 348 $string = array_map(function ($value) { 349 return explode(" ", $value); 350 }, $string); 351 foreach ($string as $val) { 352 $this->info[$val[1]] = $val[2]; 353 } 354 return $this->info; 355 } 356 } 357 358 /** 359 * memcache 关闭连接 360 * @return bool 361 * @lastTime 2014-3-29 01:11:23 362 */ 363 public function close() 364 { 365 $this->is_close = true; 366 return !!$this->socket_write("quit\r\n"); 367 } 368 369 /** 370 * 析构函数 关闭套字节 371 */ 372 public function __destruct() 373 { 374 if (is_resource($this->socket) && $this->connect_method == 'socket_create') 375 socket_close($this->socket); 376 else if ($this->connect_method) 377 fclose($this->socket); 378 } 379 380 }