【總結】PHP常見面試題彙總(三)
目錄:
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提供了很好的令牌驗證功能。