php函数的使用技巧
函数的使用技巧 1. do{...}while(false)的用法 作用:使用do{...}while(false)结构可以简化多级判断时代码的嵌套。 例子: 现在要实现一个功能,但需要A、B、C、D四个前提条件,并且这四个前提条件都存在上级依赖,即B依赖于A,C依赖于A和B,D依赖于A、B和C。如果按照一般的写法,是这样: 1. if( A==true ) 2. { 3. if( B==true ) 4. { 5. if( C==true ) 6. { 7. if( D==true ) 8. { 9. //实现功能代码 10. } 11. } 12. } 13. } 可能看出来,这样导致多层if语句嵌套,看起来逻辑很不清晰。 一种解决的办法是使用goto语句,当某个条件不成立时,直接跳转到之后的语句段,形如这样: 1. if( A==false ) 2. goto tag; 3. if( B==false ) 4. goto tag; 5. if( C==false ) 6. goto tag; 7. if( D==false ) 8. goto tag; 9. //实现功能代码 10. 11. tag: 12. ... 这样看起来风格是好多了,但使用goto语句会有很多隐患,一般是不建议用的。 其实使用do while语句也可以实现类似goto的功能,但代码可读性会比goto风格好很多。代码如下: 1. do 2. { 3. if( A==false ) 4. break; 5. if( B==false ) 6. break; 7. if( C==false ) 8. break; 9. if( D==false ) 10. break; 11. //实现功能代码 12. }while(false); 13. ... 在do{...}while(false)中的代码段,可以用break的方式实现类似goto的跳转功能,在实际工程中很有使用价值。 2. 字符串替换函数 str_replace(find, replace,string,count) find 可以是 array ,string replace 可以是 array,string 如果替换 字符串中的 特殊字符:\n,\t 字符串用 双引号 双引号 和单引号 的区别; 3. 数组转json字符串 值 有中文 但不转义为unicode 参数:JSON_UNESCAPED_UNICODE 值 有反斜杠 但是不转义反斜杠 参数:JSON_UNESCAPED_SLASHES json_encode($filter_word, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES); 4. form表单同一秒内,提交多次的问题: ①在 页面表单 提交按钮做初步限制 如:disabled属性 ajax.unbond事件 ②在提交的控制器方法中做规避:memcached缓存add方法的属性 if( ! Cache::add($key, 1, 3)) … 5. 操作数据库数据的“锁” ①“悲观锁” thinkPHP 框架中SQL语句中lock(true),“悲观锁”很容易把表“锁死”。 ②“乐观锁” 可以在 数据表中增加 一个版本字段version字段,记录当前update操作的版本。如果先select 其次 update, update中的where包含 主键和版本,如果版本不对就重新select。 ③“乐观锁”和缓存memcached 一起使用 这是我们\Common\Util\Cache.class.php文件中的方法 //该方法 可以拿到锁,$callback执行完了,释放锁. public static function lockTrans($key, \Closure $callback, $expire = 10, $tryTime = 5, $force = false) { $lock = self::lock($key, $expire, $tryTime); if ($lock || $force) $callback(); if ($lock) { self::unlock($key); return true; } return false; } 自己亦可以按照 先拿到锁 其次 执行代码 释放锁 这3个步骤来使用 缓存“乐观锁”完成相应的功能 public static function lock($key, $expire = 10, $tryTime = 5, $sleepSec = 0.1) { $cnt = 0; $lock = false; while (++$cnt <= $tryTime) { if(!!$lock = self::getInstance()->add('lock_'.$key, 1, $expire)) break; usleep($sleepSec * 1000000); } return $lock; } public static function unlock($key) { return self::rm('lock_'.$key); } 6. ThinkPHP的自增(setInc)自减(setDec) 做统计功能 public function addActivityNum($data){ if(empty($data)) return false; if(is_array($data)) $key = implode('_', $data); if(is_string($data)) $key = md5(trim($data)); //使用缓存保存各个类型中第一条数据 $flag = Cache::getOrSet($key, function ()use($data) { if($this->db4->table('t_stat_activity_num')->setMasterDB(0)->field('autoid')->where($data)->find()) { return true; } return false; }, 86400, false); if($flag) { //采用每60秒数据统一一次自增数据和数量 $up = $this->db4->table('t_stat_activity_num')->where($data)->setInc('num',1,60); } if(!$flag) { $data['num'] = 1; $up = $this->db4->table('t_stat_activity_num')->add($data); if($up) Cache::rm($key); } return $up; } 这样做的好处,操作数据库统计表 不是很频繁,减少 数据库压力。 7. session 存放在缓存服务器中共享session的功能 ① 动态修改 ini.php文件中session的配置: if(extension_loaded('memcache')){ ini_set("session.save_handler", "memcache"); ini_set("session.save_path", "tcp://127.0.0.1:11211"); } ② 切换session的驱动模式 /** * 打开Session * @access public * @param string $savePath * @param string $sessName * @return bool */ public function open($savePath ='', $sessName ='') { //session生命周期时间 $this->lifeTime = C('SESSION_EXPIRE') ? C('SESSION_EXPIRE') : $this->lifeTime; $options = array( 'timeout' => C('SESSION_TIMEOUT') ? C('SESSION_TIMEOUT') : 1, 'persistent' => C('SESSION_PERSISTENT') ? C('SESSION_PERSISTENT') : 0 ); //采用 文件缓存 和memcached缓存 驱动session $type = C('SESSION_TYPE'); //结合 框架正在使用的 缓存扩展 $this->handle = \Think\Cache::getInstance($type,$options); return true; } functions.php /** * session管理函数 * @param string|array $name session名称 如果为数组则表示进行session设置 * @param mixed $value session值 * @return mixed */ function session($name='',$value='') { $prefix = C('SESSION_PREFIX'); if(is_array($name)) { // session初始化 在session_start 之前调用 if(isset($name['prefix'])) C('SESSION_PREFIX',$name['prefix']); if(C('VAR_SESSION_ID') && isset($_REQUEST[C('VAR_SESSION_ID')])){ session_id($_REQUEST[C('VAR_SESSION_ID')]); }elseif(isset($name['id'])) { session_id($name['id']); } if('common' == APP_MODE){ // 其它模式可能不支持 ini_set('session.auto_start', 0); } if(isset($name['name'])) session_name($name['name']); if(isset($name['path'])) session_save_path($name['path']); if(isset($name['domain'])) ini_set('session.cookie_domain', $name['domain']); if(isset($name['expire'])) { ini_set('session.gc_maxlifetime', $name['expire']); ini_set('session.cookie_lifetime', $name['expire']); } if(isset($name['use_trans_sid'])) ini_set('session.use_trans_sid', $name['use_trans_sid']?1:0); if(isset($name['use_cookies'])) ini_set('session.use_cookies', $name['use_cookies']?1:0); if(isset($name['cache_limiter'])) session_cache_limiter($name['cache_limiter']); if(isset($name['cache_expire'])) session_cache_expire($name['cache_expire']); if(isset($name['type'])) C('SESSION_TYPE',$name['type']); if(C('SESSION_TYPE')) { // 读取session驱动 $type = C('SESSION_TYPE'); // $class = strpos($type,'\\')? $type : 'Think\\Session\\Driver\\'. ucwords(strtolower($type)); $class = strpos($type,'\\')? $type : 'Think\\Session\\Driver\\'. ucwords(strtolower('Session')); $hander = new $class(); session_set_save_handler( array(&$hander,"open"), array(&$hander,"close"), array(&$hander,"read"), array(&$hander,"write"), array(&$hander,"destroy"), array(&$hander,"gc")); } // 启动session if(C('SESSION_AUTO_START')) session_start(); }elseif('' === $value){ if(''===$name){ // 获取全部的session return $prefix ? $_SESSION[$prefix] : $_SESSION; }elseif(0===strpos($name,'[')) { // session 操作 if('[pause]'==$name){ // 暂停session session_write_close(); }elseif('[start]'==$name){ // 启动session session_start(); }elseif('[destroy]'==$name){ // 销毁session $_SESSION = array(); session_unset(); session_destroy(); }elseif('[regenerate]'==$name){ // 重新生成id session_regenerate_id(); } }elseif(0===strpos($name,'?')){ // 检查session $name = substr($name,1); if(strpos($name,'.')){ // 支持数组 list($name1,$name2) = explode('.',$name); return $prefix?isset($_SESSION[$prefix][$name1][$name2]):isset($_SESSION[$name1][$name2]); }else{ return $prefix?isset($_SESSION[$prefix][$name]):isset($_SESSION[$name]); } }elseif(is_null($name)){ // 清空session if($prefix) { unset($_SESSION[$prefix]); }else{ $_SESSION = array(); } }elseif($prefix){ // 获取session if(strpos($name,'.')){ list($name1,$name2) = explode('.',$name); return isset($_SESSION[$prefix][$name1][$name2])?$_SESSION[$prefix][$name1][$name2]:null; }else{ return isset($_SESSION[$prefix][$name])?$_SESSION[$prefix][$name]:null; } }else{ if(strpos($name,'.')){ list($name1,$name2) = explode('.',$name); return isset($_SESSION[$name1][$name2])?$_SESSION[$name1][$name2]:null; }else{ return isset($_SESSION[$name])?$_SESSION[$name]:null; } } }elseif(is_null($value)){ // 删除session if(strpos($name,'.')){ list($name1,$name2) = explode('.',$name); if($prefix){ unset($_SESSION[$prefix][$name1][$name2]); }else{ unset($_SESSION[$name1][$name2]); } }else{ if($prefix){ unset($_SESSION[$prefix][$name]); }else{ unset($_SESSION[$name]); } } }else{ // 设置session if(strpos($name,'.')){ list($name1,$name2) = explode('.',$name); if($prefix){ $_SESSION[$prefix][$name1][$name2] = $value; }else{ $_SESSION[$name1][$name2] = $value; } }else{ if($prefix){ $_SESSION[$prefix][$name] = $value; }else{ $_SESSION[$name] = $value; } } } return null; } Session.class.php <?php namespace Think\Session\Driver; /** * 缓存方式Session驱动 * 和 \Think\Cache.class.php 的缓存方式相结合 * Class Session * @package Think\Session\Driver */ class Session { protected $lifeTime = 1440; protected $sessionName = ''; protected $handle = null; /** * 打开Session * @access public * @param string $savePath * @param string $sessName * @return bool */ public function open($savePath ='', $sessName ='') { $this->lifeTime = C('SESSION_EXPIRE') ? C('SESSION_EXPIRE') : $this->lifeTime; $options = array( 'timeout' => C('SESSION_TIMEOUT') ? C('SESSION_TIMEOUT') : 1, 'persistent' => C('SESSION_PERSISTENT') ? C('SESSION_PERSISTENT') : 0 ); $type = C('SESSION_TYPE'); $this->handle = \Think\Cache::getInstance($type,$options); return true; } /** * 关闭Session * @access public */ public function close() { $this->gc(ini_get('session.gc_maxlifetime')); $this->handle->close(); $this->handle = null; return true; } /** * 读取Session * @access public * @param string $sessID * @return mixed */ public function read($sessID = '') { return $this->handle->get($this->sessionName.$sessID); } /** * 写入Session * @access public * @param string $sessID * @param string $sessData * @return mixed */ public function write($sessID = '', $sessData = '') { return $this->handle->set($this->sessionName.$sessID, $sessData, 0, $this->lifeTime); } /** * 删除Session * @access public * @param string $sessID * @return mixed */ public function destroy($sessID) { return $this->handle->delete($this->sessionName.$sessID); } /** * Session 垃圾回收 * @access public * @param string $sessMaxLifeTime * @return bool */ public function gc($sessMaxLifeTime) { return true; } }