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 }

 

 

posted @ 2014-03-28 03:27  iyoule  阅读(1587)  评论(0编辑  收藏  举报