【总结】PHP常见面试题汇总(三)
2016-03-01 14:59
676 查看
目录:
1、php如何在文章列表中任意位置或固定位置插入新的文章?比如:3、6位置
2、php如何删除两个数组中有交集的元素?
3、php如何在数组头部和尾部及任意位置插入元素?
4、php如何将二位数组按某一个或多个字段值(升序/降序)排序?数字索引被重置,关联索引保持不变
5、php如何实现APP版本号的比对?
6、php如何获取视频封面图?
7、php中的六种加密解密算法
8、php如何方式SQL注入?
9、php如何将模板标签替换为指定内容?
10、php如何获取当前页面的完整url?
11、php如何强制下载文件?
12、php截取字符串长度(含中文)
13、php如何获取客户端真实IP?
14、php如何记录日志信息到文件中?
15、php如何防止重复提交表单?令牌方式
1、如何在文章列表中任意位置或固定位置插入新的文章?比如:3、6位置
2、如何删除两个数组中有交集的元素?
3、如何在数组头部和尾部及任意位置插入元素?
4、如何将二位数组按某一个或多个字段值(升序/降序)排序?数字索引被重置,关联索引保持不变
5、APP版本号的比对
6、获取视频封面图
7、php加密解密:php加密和解密函数通常可以用来加密一些有用的字符串存放在数据库里或作为各个子系统间同步登陆的令牌,并且通过解密算法解密字符串,该函数使用了base64和MD5加密和解密。
①第一种加密解密算法
②第二种加密解密算法:
项目中有时我们需要使用PHP将特定的信息进行加密,也就是通过加密算法生成一个加密字符串,这个加密后的字符串可以通过解密算法进行解密,便于程序对解密后的信息进行处理。最常见的应用在用户登录以及一些API数据交换的场景。最常见的应用在用户登录以及一些API数据交换的场景。加密解密原理一般都是通过一定的加密解密算法,将密钥加入到算法中,最终得到加密解密结果。
8、php如何方式SQL注入?我们在查询数据库时,出于安全考虑,需要过滤一些非法字符防止SQL恶意注入
9、php如何将模板标签替换为指定的内容?
12、php截取字符串长度(含中文)
15、php如何防止重复提交表单?
我们提交表单的时候,不能忽视的一个限制是防止用户重复提交表单,因为有可能用户连续点击了提交按钮或者是攻击者恶意提交数据,那么我们在提交数据后的处理如修改或添加数据到数据库时就会惹上麻烦。
那么如何规避这中重复提交表单的现象出现呢?我们可以从很多方面入手,首先从前端做限制。前端JavaScript在按钮被点击一次后禁用,即disabled,这个方法简单的防止了多次点击提交按钮,但是缺点是如果用户禁用了javascript脚本则失效。第二,我们可以在提交后做redirect页面重定向,即提交后跳转到新的页面,主要避免F5重复提交,但是也有不足之处。第三,就是数据库做唯一索引约束。第四,就是做session令牌验证。
我们现在来了解下简单的利用session token来防止表单重复提交的方法。
我们在表单中加一个input隐藏域,即type="hidden",其value值用来保存token值,当页面刷新的时候这个token值会变化,提交后判断token值是否正确,如果前台提交的token与后台不匹配,则认为是重复提交。
1、php如何在文章列表中任意位置或固定位置插入新的文章?比如:3、6位置
2、php如何删除两个数组中有交集的元素?
3、php如何在数组头部和尾部及任意位置插入元素?
4、php如何将二位数组按某一个或多个字段值(升序/降序)排序?数字索引被重置,关联索引保持不变
5、php如何实现APP版本号的比对?
6、php如何获取视频封面图?
7、php中的六种加密解密算法
8、php如何方式SQL注入?
9、php如何将模板标签替换为指定内容?
10、php如何获取当前页面的完整url?
11、php如何强制下载文件?
12、php截取字符串长度(含中文)
13、php如何获取客户端真实IP?
14、php如何记录日志信息到文件中?
15、php如何防止重复提交表单?令牌方式
1、如何在文章列表中任意位置或固定位置插入新的文章?比如:3、6位置
<?php /** * 需求如下: * 1、在文章列表中的第3、6位置插入新的文章 * 2、插入的新文章不能出现在文章列表中的头部和尾部 * 3、文章列表中轮询显示最新发布的前10篇新文章(即:插入的新文章),每次显示2篇 * 4、如果新文章数量不小于10篇,那么则轮询显示;反之则只显示一遍 * **/ $pageNumber = $this->input->get_post("pageNumber",true);//上拉、下拉次数 $contentList = $this->article_model->getArticleByCategory2($cateId, 0, $offset);//$offset=8 $contentList = $this->_getContentList($contentList);//文章列表 $cache_num = 10; //缓存最新的10条新文章到mc $size = 2; //每次从mc获取2篇新文章 $max_times = $cache_num/$size;//5次取完 if($pageNumber <= $max_times){//下拉上拉次数小于等于5的情况,比如:"1、2、3、4、5、..." $offset_1 = ($pageNumber - 1) * $size;//查询的开始位置,比如:"0、2、4、6、8" }else{ if($pageNumber % $max_times){//下拉上拉次数大于5并且不能被5整除的情况,比如:"6、7、8、9、11、..." $num = $this->article_model->getPublishCountArticleByCategory($cateId);//获取mc中数据量 if($num >= $cache_num){//mc中新文章大于等于10篇的情况 $offset_1 = ($pageNumber % $max_times - 1) * $size;//轮询 }else{//mc中新文章小于10篇的情况 $offset_1 = $max_times * 2;//不轮询 } }else{//下拉上拉次数大于5并且正好能被5整除的情况,比如:"10、15、20、25、30、..." $num = $this->article_model->getPublishCountArticleByCategory($cateId);//获取mc中数据量 if($num >= $cache_num){//mc中新文章大于等于10篇的情况 $offset_1 = $cache_num - $size;//轮询 }else{//mc中新文章小于10篇的情况 $offset_1 = $max_times * 2;//不轮询 } } } $publishList = $this->article_model->getPublishArticleByCategory($cateId, $offset_1,$size,$cache_num);//随机获取两条新文章 $publishList = $this->_getPublishList($publishList);//从mc中获取2篇新文章插入到文章列表中 $content_count = count($contentlist); $publish_count = count($publishlist); if(!empty($publishList)){//3、6位置是预留位置 if( ($content_count >= 3) && ($publish_count >= 1) ){ $publishList_new[0] = $publishList[0];//组装成一个二维数组 array_splice($contentList,3-1,0,$publishList_new);//第3的位置(索引为3-1)插入第1篇新文章 } if( ($content_count >= 6) && ($publish_count >= 2) ){ $publishList_new[0] = $publishList[1];//组装成一个二维数组 array_splice($contentList,6-1,0,$publishList_new);//第6的位置(索引为6-1)插入第2篇新文章 } } ?>
2、如何删除两个数组中有交集的元素?
foreach($content_list_temp_recommend as $k=>$v){ $kk=array_search($v['aid'], $aid_arr_temp);//$v['aid']必定是$aid_arr_temp数组内元素之一的情况 $msg.=$aid_arr_temp[$kk].","; if($kk !== false){//只要不是false就是找到了 unset($aid_arr_temp[$kk]);//删除后,索引键保持不变 } } $aid_arr= array_values($aid_arr_temp);//经过array_values()函数处理过后,索引键重新分配。
3、如何在数组头部和尾部及任意位置插入元素?
①插入元素 array_unshift();//在数组头部插入一个或多个元素 array_push();//在数组尾部插入一个或多个元素 array_splice($arr,$start,0,$arr1);//在数组的第$start+1个位置插入新元素(指的是头部和中部任意位置,但不包括尾部),注意:参数3一定要是0 ②删除元素 array_shift();//删除数组中首个元素,并返回删除后的值 array_pop();//删除数组的最后一个元素(出栈),并返回删除后的值
4、如何将二位数组按某一个或多个字段值(升序/降序)排序?数字索引被重置,关联索引保持不变
$arr=array( array('id'=>1,'name'=>'will','age'=>23), array('id'=>2,'name'=>'myth','age'=>32), array('id'=>3,'name'=>'allen','age'=>27), array('id'=>4,'name'=>'martin','age'=>23) ); foreach($arr as $k=>$v){ $tag1[]=$v['age']; //age排序字段 $tag2[]=$v['id']; //id排序字段 } //相当于 select * from $arr order by $tag1 DESC,$tag2 ASC;//特点:$tag1、$tag2、$arr数组的元素个数必须要一致 array_multisort($tag1,SORT_DESC,$tag2,SORT_ASC,$arr);//根据年龄从大到小排列,年龄相同则按id升序排列 echo "<pre>";print_r($arr);exit; ?>
<?php //php二维数组如何按照指定列进行排序? function arrSortByField(&$list, $field, $call_func=NULL, $sort_type=SORT_ASC){//引用传值 $sort_filed = array(); foreach ($list as $val) { if (!isset($val[$field])) return false; $sort_filed[] = is_null($call_func) ? $val[$field] : call_user_func($call_func,$val[$field]); } return array_multisort($sort_field,$sort_type,$list);//$list顺序会随$sort_field顺序变化而变化 } $list= array( array('id' =>3, 'name' => 'asdfsdf'), array('id' =>1, 'name' => '12'), array('id' =>4, 'name' => '10sdf'), array('id' =>2, 'name' => 'ada'), array('id' =>5, 'name' => 'aasdfbc') ); arrSortByField($list,'name','strlen');//按照 "name" 列的值长度进行排序 echo "<pre>";print_r($list); arrSortByField($list,'id');//按照 "id" 列的值大小进行排序 echo "<pre>";print_r($list); ?>
5、APP版本号的比对
<?php header("content-type:text/html;charset=utf-8"); date_default_timezone_set('Asia/Shanghai'); function _diffVersion($current,$update){ if($current == "null"){ return false; } $currentVersion = getVersion($current); $updateVersion = getVersion($update); if($currentVersion['mainVersion'] < $updateVersion['mainVersion']){ return true; }else if($currentVersion['mainVersion'] == $updateVersion['mainVersion']){ if($currentVersion['minVersion'] < $updateVersion['minVersion']){ return true; }else if($currentVersion['minVersion'] > $updateVersion['minVersion']){ return false; } if($currentVersion['fixVersion'] < $updateVersion['fixVersion']){ return true; } } return false; } function getVersion($version){ $result = array(); if(strstr($version,".")){ $data = explode(".",$version); $result['mainVersion'] = $data[0]; if(isset($data[1])){ $result['minVersion'] = $data[1]; }else{ $result['minVersion'] = 0; } if(isset($data[2])){ $result['fixVersion'] = $data[2]; }else{ $result['fixVersion'] = 0; } } return $result; } echo "<pre>";print_r(_diffVersion("2.0.0","2.0.01"));//true-需要升级 false-不升级 ?>
6、获取视频封面图
<?php header("content-type:text/html;charset=utf-8"); date_default_timezone_set('Asia/Shanghai'); function getCoverImages($fileUrl){ $result = array(); if(!empty($fileUrl)){ $filePath = str_replace("http://img.baidu.cn/", "/data/images/", $fileUrl); if(is_file($filePath)){ $result = execCommandLine($filePath); } } return json_encode($result); } function execCommandLine($file){ $result = array(); $pathParts = pathinfo($file); $filename = $pathParts['dirname']."/".$pathParts['filename']."_"; $times = array(8,15,25); foreach ($times as $k => $v) { $destFilePath = $filename.$v.".jpg"; $command = "/usr/bin/ffmpeg -i {$file} -y -f image2 -ss {$v} -vframes 1 -s 640x360 {$destFilePath}"; exec($command); //chmod($filename.$v."jpg",0644); $destUrlPath = str_replace("/data/images/", "http://img.baidu.cn/", $destFilePath); $selected = $k == 0 ? "1" : "0";//默认将第一张图片作为封面图 array_push($result,array($destUrlPath,$selected)); } return $result; } $fileUrl="http://img.baidu.cn/14221916FLVSDT1.mp4" getCoverImages($fileUrl);//截取第8、15、25秒为封面图 ?>
7、php加密解密:php加密和解密函数通常可以用来加密一些有用的字符串存放在数据库里或作为各个子系统间同步登陆的令牌,并且通过解密算法解密字符串,该函数使用了base64和MD5加密和解密。
①第一种加密解密算法
<?php function encryptDecrypt($key, $string, $decrypt){ if($decrypt){ $decrypted = rtrim(mcrypt_decrypt(MCRYPT_RIJNDAEL_256, md5($key), base64_decode($string), MCRYPT_MODE_CBC, md5(md5($key))), "12"); return $decrypted; }else{ $encrypted = base64_encode(mcrypt_encrypt(MCRYPT_RIJNDAEL_256, md5($key), $string, MCRYPT_MODE_CBC, md5(md5($key)))); return $encrypted; } } //加密:"z0JAx4qMwcF+db5TNbp/xwdUM84snRsXvvpXuaCa4Bk=" echo encryptDecrypt('password', 'Helloweba欢迎您',0); //解密:"Helloweba欢迎您" echo encryptDecrypt('password', 'z0JAx4qMwcF+db5TNbp/xwdUM84snRsXvvpXuaCa4Bk=',1); ?>
②第二种加密解密算法:
<?php //加密函数 function lock_url($txt,$key='www.zhuoyuexiazai.com'){ $chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-=+"; $nh = rand(0,64); $ch = $chars[$nh]; $mdKey = md5($key.$ch); $mdKey = substr($mdKey,$nh%8, $nh%8+7); $txt = base64_encode($txt); $tmp = ''; $i=0;$j=0;$k = 0; for ($i=0; $i<strlen($txt); $i++) { $k = $k == strlen($mdKey) ? 0 : $k; $j = ($nh+strpos($chars,$txt[$i])+ord($mdKey[$k++]))%64; $tmp .= $chars[$j]; } return urlencode($ch.$tmp); } //解密函数 function unlock_url($txt,$key='www.zhuoyuexiazai.com'){ $txt = urldecode($txt); $chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-=+"; $ch = $txt[0]; $nh = strpos($chars,$ch); $mdKey = md5($key.$ch); $mdKey = substr($mdKey,$nh%8, $nh%8+7); $txt = substr($txt,1); $tmp = ''; $i=0;$j=0; $k = 0; for ($i=0; $i<strlen($txt); $i++) { $k = $k == strlen($mdKey) ? 0 : $k; $j = strpos($chars,$txt[$i])-$nh - ord($mdKey[$k++]); while ($j<0) $j+=64; $tmp .= $chars[$j]; } return base64_decode($tmp); } ?>③第三种加密解密算法:
<?php //改进后的算法 //加密函数 function lock_url($txt,$key='zhuoyuexiazai'){ $txt = $txt.$key; $chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-=+"; $nh = rand(0,64); $ch = $chars[$nh]; $mdKey = md5($key.$ch); $mdKey = substr($mdKey,$nh%8, $nh%8+7); $txt = base64_encode($txt); $tmp = ''; $i=0;$j=0;$k = 0; for ($i=0; $i<strlen($txt); $i++) { $k = $k == strlen($mdKey) ? 0 : $k; $j = ($nh+strpos($chars,$txt[$i])+ord($mdKey[$k++]))%64; $tmp .= $chars[$j]; } return urlencode(base64_encode($ch.$tmp)); } //解密函数 function unlock_url($txt,$key='zhuoyuexiazai'){ $txt = base64_decode(urldecode($txt)); $chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-=+"; $ch = $txt[0]; $nh = strpos($chars,$ch); $mdKey = md5($key.$ch); $mdKey = substr($mdKey,$nh%8, $nh%8+7); $txt = substr($txt,1); $tmp = ''; $i=0;$j=0; $k = 0; for ($i=0; $i<strlen($txt); $i++) { $k = $k == strlen($mdKey) ? 0 : $k; $j = strpos($chars,$txt[$i])-$nh - ord($mdKey[$k++]); while ($j<0) $j+=64; $tmp .= $chars[$j]; } return trim(base64_decode($tmp),$key); } ?>④第四种加密解密算法:
<?php function passport_encrypt($txt, $key = 'www.zhuoyuexiazai.com') { srand((double)microtime() * 1000000); $encrypt_key = md5(rand(0, 32000)); $ctr = 0; $tmp = ''; for($i = 0;$i < strlen($txt); $i++) { $ctr = $ctr == strlen($encrypt_key) ? 0 : $ctr; $tmp .= $encrypt_key[$ctr].($txt[$i] ^ $encrypt_key[$ctr++]); } return urlencode(base64_encode(passport_key($tmp, $key))); } function passport_decrypt($txt, $key = 'www.zhuoyuexiazai.com') { $txt = passport_key(base64_decode(urldecode($txt)), $key); $tmp = ''; for($i = 0;$i < strlen($txt); $i++) { $md5 = $txt[$i]; $tmp .= $txt[++$i] ^ $md5; } return $tmp; } function passport_key($txt, $encrypt_key) { $encrypt_key = md5($encrypt_key); $ctr = 0; $tmp = ''; for($i = 0; $i < strlen($txt); $i++) { $ctr = $ctr == strlen($encrypt_key) ? 0 : $ctr; $tmp .= $txt[$i] ^ $encrypt_key[$ctr++]; } return $tmp; } $txt = "1"; $key = "testkey"; $encrypt = passport_encrypt($txt,$key); $decrypt = passport_decrypt($encrypt,$key); echo $encrypt."<br>"; echo $decrypt."<br>"; ?>⑤第五种加密解密算法:discuz中使用的加密解密算法
项目中有时我们需要使用PHP将特定的信息进行加密,也就是通过加密算法生成一个加密字符串,这个加密后的字符串可以通过解密算法进行解密,便于程序对解密后的信息进行处理。最常见的应用在用户登录以及一些API数据交换的场景。最常见的应用在用户登录以及一些API数据交换的场景。加密解密原理一般都是通过一定的加密解密算法,将密钥加入到算法中,最终得到加密解密结果。
<?php //非常给力的authcode加密函数,Discuz!经典代码(带详解) //函数authcode($string, $operation, $key, $expiry)中的$string:字符串,明文或密文;$operation:DECODE表示解密,其它表示加密;$key:密匙;$expiry:密文有效期。 function authcode($string, $operation = 'DECODE', $key = '', $expiry = 0) { // 动态密匙长度,相同的明文会生成不同密文就是依靠动态密匙 $ckey_length = 4; // 密匙 $key = md5($key ? $key : $GLOBALS['discuz_auth_key']); // 密匙a会参与加解密 $keya = md5(substr($key, 0, 16)); // 密匙b会用来做数据完整性验证 $keyb = md5(substr($key, 16, 16)); // 密匙c用于变化生成的密文 $keyc = $ckey_length ? ($operation == 'DECODE' ? substr($string, 0, $ckey_length): substr(md5(microtime()), -$ckey_length)) : ''; // 参与运算的密匙 $cryptkey = $keya.md5($keya.$keyc); $key_length = strlen($cryptkey); // 明文,前10位用来保存时间戳,解密时验证数据有效性,10到26位用来保存$keyb(密匙b), //解密时会通过这个密匙验证数据完整性 // 如果是解码的话,会从第$ckey_length位开始,因为密文前$ckey_length位保存 动态密匙,以保证解密正确 $string = $operation == 'DECODE' ? base64_decode(substr($string, $ckey_length)) : sprintf('%010d', $expiry ? $expiry + time() : 0).substr(md5($string.$keyb), 0, 16).$string; $string_length = strlen($string); $result = ''; $box = range(0, 255); $rndkey = array(); // 产生密匙簿 for($i = 0; $i <= 255; $i++) { $rndkey[$i] = ord($cryptkey[$i % $key_length]); } // 用固定的算法,打乱密匙簿,增加随机性,好像很复杂,实际上对并不会增加密文的强度 for($j = $i = 0; $i < 256; $i++) { $j = ($j + $box[$i] + $rndkey[$i]) % 256; $tmp = $box[$i]; $box[$i] = $box[$j]; $box[$j] = $tmp; } // 核心加解密部分 for($a = $j = $i = 0; $i < $string_length; $i++) { $a = ($a + 1) % 256; $j = ($j + $box[$a]) % 256; $tmp = $box[$a]; $box[$a] = $box[$j]; $box[$j] = $tmp; // 从密匙簿得出密匙进行异或,再转成字符 $result .= chr(ord($string[$i]) ^ ($box[($box[$a] + $box[$j]) % 256])); } if($operation == 'DECODE') { // 验证数据有效性,请看未加密明文的格式 if((substr($result, 0, 10) == 0 || substr($result, 0, 10) - time() > 0) && substr($result, 10, 16) == substr(md5(substr($result, 26).$keyb), 0, 16)) { return substr($result, 26); } else { return ''; } } else { // 把动态密匙保存在密文里,这也是为什么同样的明文,生产不同密文后能解密的原因 // 因为加密后的密文可能是一些特殊字符,复制过程可能会丢失,所以用base64编码 return $keyc.str_replace('=', '', base64_encode($result)); } } $str = 'abcdef'; $key = 'www.helloweba.com'; echo authcode($str,'ENCODE',$key,0); //加密 $str = '56f4yER1DI2WTzWMqsfPpS9hwyoJnFP2MpC8SOhRrxO7BOk'; echo authcode($str,'DECODE',$key,0); //解密 ?>⑥第六种加密解密算法:
<?php //函数encrypt($string,$operation,$key)中$string:需要加密解密的字符串;$operation:判断是加密还是解密,E表示加密,D表示解密;$key:密匙。 function encrypt($string,$operation,$key=''){ $key=md5($key); $key_length=strlen($key); $string=$operation=='D'?base64_decode($string):substr(md5($string.$key),0,8).$string; $string_length=strlen($string); $rndkey=$box=array(); $result=''; for($i=0;$i<=255;$i++){ $rndkey[$i]=ord($key[$i%$key_length]); $box[$i]=$i; } for($j=$i=0;$i<256;$i++){ $j=($j+$box[$i]+$rndkey[$i])%256; $tmp=$box[$i]; $box[$i]=$box[$j]; $box[$j]=$tmp; } for($a=$j=$i=0;$i<$string_length;$i++){ $a=($a+1)%256; $j=($j+$box[$a])%256; $tmp=$box[$a]; $box[$a]=$box[$j]; $box[$j]=$tmp; $result.=chr(ord($string[$i])^($box[($box[$a]+$box[$j])%256])); } if($operation=='D'){ if(substr($result,0,8)==substr(md5(substr($result,8).$key),0,8)){ return substr($result,8); }else{ return''; } }else{ return str_replace('=','',base64_encode($result)); } } $str = 'abc'; $key = 'www.helloweba.com'; $token = encrypt($str, 'E', $key); echo '加密:'.encrypt($str, 'E', $key); echo '解密:'.encrypt($str, 'D', $key); ?>
8、php如何方式SQL注入?我们在查询数据库时,出于安全考虑,需要过滤一些非法字符防止SQL恶意注入
<?php //我们在查询数据库时,出于安全考虑,需要过滤一些非法字符防止SQL恶意注入 function injCheck($sql_str) { $check = preg_match('/select|insert|update|delete|\'|\/\*|\*|\.\.\/|\.\/|union|into|load_file|outfile/', $sql_str); if ($check) { echo '非法字符!!'; exit; } else { return $sql_str; } } echo injCheck('1 or 1=1');//提示:"非法字符!!" ?>
9、php如何将模板标签替换为指定的内容?
<?php //有时我们需要将字符串、模板标签替换成指定的内容,可以用到下面的函数: function stringParser($string,$replacer){ $result = str_replace(array_keys($replacer), array_values($replacer),$string); return $result; } $string = 'The {b}anchor text{/b} is the {b}actual word{/b} or words used {br}to describe the link {br}itself'; $replace_array = array('{b}' => '<b>','{/b}' => '</b>','{br}' => '<br />'); echo stringParser($string,$replace_array); ?>10、php如何获取当前页面的url?如:"https://www.baidu.com/index.php?username=xiaoqiang"
<?php //以下函数可以获取当前页面的URL,不管是http还是https function curPageURL() { $pageURL = 'http'; if (!empty($_SERVER['HTTPS'])) {$pageURL .= "s";} $pageURL .= "://"; if ($_SERVER["SERVER_PORT"] != "80") { $pageURL .= $_SERVER["SERVER_NAME"].":".$_SERVER["SERVER_PORT"].$_SERVER["REQUEST_URI"]; } else { $pageURL .= $_SERVER["SERVER_NAME"].$_SERVER["REQUEST_URI"]; } return $pageURL; } echo curPageURL(); ?>11、php如何强制下载文件?
<?php //有时我们不想让浏览器直接打开文件,如PDF文件,而是要直接下载文件,那么以下函数可以强制下载文件,函数中使用了application/octet-stream头类型 function download($filename){ if ((isset($filename))&&(file_exists($filename))){ header("Content-length: ".filesize($filename)); header('Content-Type: application/octet-stream'); header('Content-Disposition: attachment; filename="' . $filename . '"'); readfile("$filename"); } else { echo "Looks like file does not exist!"; } } download('/down/test_45f73e852.zip'); ?>
12、php截取字符串长度(含中文)
<?php //我们经常会遇到需要截取字符串(含中文汉字)长度的情况,比如标题显示不能超过多少字符,超出的长度用...表示,以下函数可以满足你的需求 /* Utf-8、gb2312都支持的汉字截取函数 cut_str(字符串, 截取长度, 开始长度, 编码); 编码默认为 utf-8 开始长度默认为 0 */ function cutStr($string, $sublen, $start = 0, $code = 'UTF-8'){ if($code == 'UTF-8'){ $pa = "/[\x01-\x7f]|[\xc2-\xdf][\x80-\xbf]|\xe0[\xa0-\xbf][\x80-\xbf]|[\xe1-\xef][\x80-\xbf][\x80-\xbf]|\xf0[\x90-\xbf][\x80-\xbf][\x80-\xbf]|[\xf1-\xf7][\x80-\xbf][\x80-\xbf][\x80-\xbf]/"; preg_match_all($pa, $string, $t_string); if(count($t_string[0]) - $start > $sublen) return join('', array_slice($t_string[0], $start, $sublen))."..."; return join('', array_slice($t_string[0], $start, $sublen)); }else{ $start = $start*2; $sublen = $sublen*2; $strlen = strlen($string); $tmpstr = ''; for($i=0; $i<$strlen; $i++){ if($i>=$start && $i<($start+$sublen)){ if(ord(substr($string, $i, 1))>129){ $tmpstr.= substr($string, $i, 2); }else{ $tmpstr.= substr($string, $i, 1); } } if(ord(substr($string, $i, 1))>129) $i++; } if(strlen($tmpstr)<$strlen ) $tmpstr.= "..."; return $tmpstr; } } $str = "jQuery插件实现的加载图片和页面效果"; echo cutStr($str,16);//结果:jQuery插件实现的加载图片和... ?>13、php如何获取客户端真实IP?
<?php //我们经常要用数据库记录用户的IP,以下代码可以获取客户端真实的IP: //获取用户真实IP function getIp() { if (getenv("HTTP_CLIENT_IP") && strcasecmp(getenv("HTTP_CLIENT_IP"), "unknown")) $ip = getenv("HTTP_CLIENT_IP"); else if (getenv("HTTP_X_FORWARDED_FOR") && strcasecmp(getenv("HTTP_X_FORWARDED_FOR"), "unknown")) $ip = getenv("HTTP_X_FORWARDED_FOR"); else if (getenv("REMOTE_ADDR") && strcasecmp(getenv("REMOTE_ADDR"), "unknown")) $ip = getenv("REMOTE_ADDR"); else if (isset ($_SERVER['REMOTE_ADDR']) && $_SERVER['REMOTE_ADDR'] && strcasecmp($_SERVER['REMOTE_ADDR'], "unknown")) $ip = $_SERVER['REMOTE_ADDR']; else $ip = "unknown"; return ($ip); } echo getIp();//结果:您的IP是:221.223.234.138 ?>14、php如何记录日志信息到文件中?
<?php //我们在测试代码的时候,需要了解代码执行情况,而这中执行时在后台运行的,前台无法知道是否运行正常,在这种情况下,我们一般用写日志的形式来调试代码。 function logResult($str='') { $fp = fopen("log.txt","a"); flock($fp, LOCK_EX) ; fwrite($fp,"执行日期:".strftime("%Y%m%d%H%M%S",time())."\n".$str."\n"); flock($fp, LOCK_UN); fclose($fp); } //函数logResult()记录执行时间,参数$str自定义,执行时会将运行日志写入到log.txt文件中,注意log.txt要有写权限。比如我们想知道支付接口返回的数据信息,可以这样调用: logResult('获取数据reselt=xxx'); ?>
15、php如何防止重复提交表单?
我们提交表单的时候,不能忽视的一个限制是防止用户重复提交表单,因为有可能用户连续点击了提交按钮或者是攻击者恶意提交数据,那么我们在提交数据后的处理如修改或添加数据到数据库时就会惹上麻烦。
那么如何规避这中重复提交表单的现象出现呢?我们可以从很多方面入手,首先从前端做限制。前端JavaScript在按钮被点击一次后禁用,即disabled,这个方法简单的防止了多次点击提交按钮,但是缺点是如果用户禁用了javascript脚本则失效。第二,我们可以在提交后做redirect页面重定向,即提交后跳转到新的页面,主要避免F5重复提交,但是也有不足之处。第三,就是数据库做唯一索引约束。第四,就是做session令牌验证。
我们现在来了解下简单的利用session token来防止表单重复提交的方法。
我们在表单中加一个input隐藏域,即type="hidden",其value值用来保存token值,当页面刷新的时候这个token值会变化,提交后判断token值是否正确,如果前台提交的token与后台不匹配,则认为是重复提交。
<?php /* * PHP简单利用token防止表单重复提交 */ session_start(); header("Content-Type: text/html;charset=utf-8"); function set_token() { $_SESSION['token'] = md5(microtime(true)); } function valid_token() { $return = $_REQUEST['token'] === $_SESSION['token'] ? true : false; set_token(); return $return; } //如果token为空则生成一个token if(!isset($_SESSION['token']) || $_SESSION['token']=='') { set_token(); } if(isset($_POST['web'])){ if(!valid_token()){ echo "token error,请不要重复提交!"; }else{ echo '成功提交,Value:'.$_POST['web']; } }else{ ?> <form method="post" action=""> <input type="hidden" name="token" value="<?php echo $_SESSION['token']?>"> <input type="text" class="input" name="web" value="www.helloweba.com"> <input type="submit" class="btn" value="提交" /> </form> <?php } ?>以上是一个简单的防止重复提交表单的例子,仅供参考。那么实际项目开发中,会对表单token做更复杂的处理,即我们说的令牌验证。可能要做的处理有:验证来源域,即来路,是否为外部提交;匹配要执行的动作,是添加、修改or删除;其次最重要的是构建token,token可以采用可逆的加密算法,尽可能复杂,因为明文还是不安全的。令牌验证的具体算法可以参考各大PHP框架,如ThinkPHP提供了很好的令牌验证功能。
相关文章推荐
- FAQ 前端面试大杂烩2
- 程序员才看得明白的面试圣经
- 苦逼码农与老板关于加薪的斗智斗勇
- Java程序员修炼之道 之 Logging(3/3) - 怎么分析Log
- Java程序员修炼之道 之 Logging(2/3) - 怎么写Log
- Java程序员修炼之道 之 Logging(1/3) - Logback 配置
- 分享一道JS前端闭包面试题
- java高级面试题1
- 数据库常见面试题总结
- 33条C#和.NET经典面试题目及答案
- sql面试
- iOS面试题汇总
- 驴妈妈面试总结
- 程序员,你的简历应该这样弄
- 程序员路上的那些不懂事
- Markdown码农教程
- 【程序员的爱情】彼岸花开谁又种下了执念
- 2016最新整理面试题
- 被面试到的一则算法题目: 无序列数组里面,求最长的连续数的长度
- .NET面试题解析(01)-值类型与引用类型