PHP面試題目

服務器方面php

一、nginx平滑重啓html

nginx 運行新的工做進程並從容關閉舊的工做進程,通知工做進程關閉監聽套接字,可是繼續爲當前鏈接的客戶提供服務。全部的客戶端的服務完成後,舊的工做進程被
關閉。若是新的配置文件應用失敗,nginx 將繼續使用舊的配置文件進行工做。
說簡單點就是 nginx會繼續處理以前的請求,而且啓動一個新的進程來處理新的請求,舊的進程處理完成以後會被kill。mysql

二、獲取文件後10行。
tail -10 a.lognginx

三、查看佔用系統資源比較多的進程
top
ps:輸完top命令以後,按1能夠看內存以及cpu使用狀況正則表達式

三、查看關鍵字出現函數
grep -n ‘我是要查找的關鍵字’ a.txt | cut -d 「:」 - f1

統計文件中關鍵字分別出現的哪一行:
grep -n "關鍵字"    「文件路徑」 | cut -d ":"  -f1
統計文件中關鍵字出現的最後一行行號:
grep -n "關鍵字"    「文件路徑」 | tail -n 1 | cut -d ":"  -f1redis


四、在/root/目錄下搜索帶有關鍵字「www」的文件,在終端下運行命令:
find /root/ –type f | xargs grep 「www算法

五、統計文件 行數
wc -l a.txt sql

統計demo目錄下,js文件數量:
find demo/ -name "*.js" |wc -l
統計demo目錄下全部js文件代碼行數:
find demo/ -name "*.js" |xargs cat|wc -l 
 wc -l `find ./ -name "*.js"`|tail -n1
統計demo目錄下全部js文件代碼行數,過濾了空行:
find /demo -name "*.js" |xargs cat|grep -v ^$|wc -l數據庫

六、實時監控一個文件
tail -f a.log後端

七、nginx日誌中訪問最多的100個ip及訪問次數
nginx日誌中訪問最多的100個ip及訪問次數
awk '{print $1}' /opt/software/nginx/logs/access.log| sort | uniq -c | sort -n -k 1 -r | head -n 100


八、在編譯完成的php,添加新的擴展
-----------------------------------------
源碼安裝
一、找到php的源碼目錄
二、跳轉到EXT目錄下邊
三、執行phpize生成configure文件
四、 ./configure --with-php-config=/usr/local/php/bin/php-config
五、編譯 make
六、編譯安裝 make install
七、修改php.ini extension=/usr/local/***.so
八、重啓php-fpm

YUM安裝:

一、去PHP的官網下載源碼 (htpp://pecl.php.net)
二、解壓文件
三、執行phpize生成configure文件
四、 ./configure --with-php-config=/usr/local/php/bin/php-config
五、編譯 make
六、編譯安裝 make install
七、修改php.ini extension=/usr/local/***.so
八、重啓php-fpm
-----------------------------------------

 

php優化 nginx優化 mysql優化

php優化:
一、將類的方法定義爲static。
二、儘可能使用單引號。
三、修改php-fpm進程數。
四、修改單個腳本最大可以使用內存。
五、大的數組使用完以後要及時釋放。
六、循環的時候,制定最大循環次數
七、不使用@屏蔽錯誤
八、儘可能採用大量的 PHP 內置函數
九、使用require代替require_once

nginx優化:
一、修改nginx的子進程數。 [ 最多65535 ]
二、開啓靜態緩存
三、修改主進程數。建議按照cpu 數目來指定,通常爲它的倍數 (如,2個四核的cpu計爲8)
四、開啓gzip輸出 [ 開啓gzip,ob函數就不能用了 ]
五、keepalive_timeout 設置鏈接超時時間

mysql優化:
一、避免子查詢
二、有順序的讀取
三、避免重複的讀寫
四、設置自增id
五、避免使用select *
六、合理設置字段類型
七、讀寫分離
八、分區、分表
九、創建合適的索引
十、避免使用耗費資源的操做 null
十一、不要使用rand()
十二、儘可能不要使用 or 查詢
1三、查詢一條數據的時候加上LIMIT 1
1四、開啓查詢緩存
1五、前期對數據進行合理的評估,進行分區、分表
1六、避免使用 %前綴的模糊查詢
1七、避免使用mysql自帶函數
1八、使用多從解決查詢慢的問題

 

秒殺如何實現?


咱們作的秒殺併發量就是十幾萬、下邊的版本是十幾萬的:

一、專門對秒殺服務器 [ps:量大的話這麼說,若是小的話就不用了 ]
二、生成靜態頁面。 [ ps:若是還很大的能夠把這個文件放在 cdn上 ]
三、倒計時以及庫存從服務端獲取 [ 一段時間內只獲取一次,倒計時結束以後會請求下服務端,是否已經開始 ]
四、把要秒殺的數據庫存放到redis中 [ key value ] stock=10
五、設置一個redis隊列 [ 使用list作隊列 ] lpop rpush
六、用戶在請求的時候,判斷用戶是否參與過秒殺,沒有參加過把用戶數據寫入隊列中,同時庫存減1 ,參加過就提示已經參加過
ps:這塊用到了redid的原子性操做、以及事務 multi 和 watch
redis樂觀鎖 cas ==== 就是設置以前判斷下這個值有沒有改變
七、庫存減0就不能進行秒殺
八、異步腳本處理隊列數據 [ crontab + php文件 ]

若是你說是1-3萬的話,就不用單獨去租服務器了


若是問到業務相關的問題的話,就隨機應變吧!!!!

好比說: 10 個用戶買了都不支付怎麼辦?
第一種說法 :
就說當時的產品需求是不支付也沒有問題,其它用戶也不能夠買了,當時在作的和產品討論了,產品說正常的話用戶都會支付,由於比較便宜
第二種說法:
會開啓下一輪的秒殺。 好比說小米的 2小時以後還能夠繼續買!!
第三站說法:
會。。。。

怎麼保證不超買 ?
減庫存的時候是原子性操做,使用cas樂觀鎖。測試的時候沒有出現過超買的狀況

還有就是秒殺的時候就不用購物車了,點擊的時候就排隊了


Q1:防刷是怎麼作的?通常搶購都有很大優惠。若是有人惡意刷,那正常的用戶就失去了購買的機會。好比,搶購的商品數爲1000,有人惡意刷了900,那只有 100 被正經常使用戶搶到。
等惡意搶到的 900 通過後面的支付環節驗證後,可能已通過了搶購時間了。就算惡意搶到的 900 都支付成功,那對正經常使用戶也是不公平的。
在這個業務場景中,咱們作的是商品展現、商品的購買權的發放,真正產生消費是在第三方。那麼,用戶刷的問題,須要咱們和第三方支付頁面一塊兒來控制。在用戶經過排
隊機制,得到了購買名額後,跳轉去第三方時候,咱們按照和第三方約定的加密方式傳遞加密信息,第三方按照約定的解密方式解密成功後才容許用戶支付,加密解密的過程當中能夠
帶具備生命週期的內容。這樣,用戶在高頻請求支付頁面獲取商品時候,實際只有:1)加密對;2)第一次,纔可能得到。不過,第三方都是爲了銷售出商品,因此這類合做的成功
概率不大。惡意刷,的確會在咱們的業務層面展現商品沒量了。致使想買的用戶沒了機會,但能夠保證第三方不受損。這種刷的狀況,若想在咱們業務層規避,我想這就是一個通用
的防SPAM的問題了。這塊本身真懂得很少。

Q2:要想準確的放刷,判斷的維度就多,邏輯就複雜;與之矛盾的,搶購要求的是響應迅速。
對的,搶購業務由於請求壓力大、熱門商品搶購併發高,切忌增長過多邏輯,切忌過多後端依賴,越簡單效果越好。咱們在設計系統時候,不少事不是我們一個系統能cover
的,多少須要一些前置模塊、能力的構建ready後,咱們的系統才能run的不錯。建議構建賬號體系、用戶消費記錄這兩部分。
Q3:對帳只是和第三方去對比商品的庫存量嗎,金額是否去對比?
對帳,實際上是對比的消費數據。避免出現咱們統計今日產生了X件商品共價值Y的消費,第三方給出的是消費了N件共M價值的消費。避免金額不一致,形成結算、分紅等問題的出現。
我想你問題中的庫存量的diff問題,還得靠第三方按期的經過咱們數據層的接口來update他們提供的商品。其實在咱們的商品庫中,商品不必定只容許第三方提供,也能夠容許第三
方經過接口減小商品嘛,好比和一個賣水果的第三方合做,第三方上週發佈說有100件,但這周線下熱銷,只剩20件了,咱們也應該容許第三方來update到一個低值。但這樣,咱們
的系統中就會複雜挺多。

Q4:防刷,避免第三方的推廣效果達不到問題。
對的,用戶ID維度、IP維度,都是有效辦法。看具體場景。有賬號體系的業務,用用戶ID維度效果最好,藉助存儲記錄下每一個用戶的購買記錄,來控制就好。市面上的電商
網站,基本是搶購業務都須要登陸,而且限制每件商品單人購買數量,其實就是經過存儲記錄用戶的消費,而且再次產生消費前查詢並增長代碼邏輯來控制。

Q5:每次搶購活動的時候用一套新的驗證碼?
驗證碼這個東東,屬於圖靈測試嘛,只要測試方法好,而且儘量保證每次產生的驗證信息從未出現過且無規律,就是好的驗證碼啦。

 


比較好的秒殺系統架構:
http://www.csdn.net/article/2014-11-07/2822545
http://www.kuqin.com/shuoit/20141203/343669.html

 

算法題:


http://blog.csdn.net/frimish/article/details/48666485

怎麼在海量數據中找出重複次數最多的一個

網站日誌中記錄了用戶的IP,找出訪問次數最多的IP

假設有1kw個身份證號,以及他們對應的數據。身份證號可能重複,要求找出出現次數最多的身份證號。
 
有一個1G大小的一個文件,裏面每一行是一個詞,詞的大小不超過16字節,內存限制大小是1M。返回頻數最高的100個詞。

有10個文件,每一個文件1G,每一個文件的每一行存放的都是用戶的query,每一個文件的query均可能重複。要求你按照query的頻度排序。

常見的排序:
http://www.php100.com/html/php/rumen/2013/1029/6333.html

冒泡排序:
原理:
把第一個數字和全部數字進行比較,而後遇到大的交換位置,這樣第一次就把最大的放在了最後邊,而後繼續在比較,第二次比較的時候最後一個數字就不
用比較了,由於已經肯定它是最大的了,以此類推。

1. 冒泡排序法 
 *     思路分析:法如其名,就是像冒泡同樣,每次從數組當中 冒一個最大的數出來。 
 *     好比:2,4,1    // 第一次 冒出的泡是4 
 *                2,1,4   // 第二次 冒出的泡是 2 
 *                1,2,4   // 最後就變成這樣 

時間複雜度:
冒泡排序是一種用時間換空間的排序方法,最壞狀況是把順序的排列變成逆序,或者把逆序的數列變成順序。

$arr=array(1,43,54,62,21,66,32,78,36,76,39);
function getpao($arr)
{
$len=count($arr);
//設置一個空數組 用來接收冒出來的泡
//該層循環控制 須要冒泡的輪數
for($i=1;$i<$len;$i++)
{ //該層循環用來控制每輪 冒出一個數 須要比較的次數
for($k=0;$k<$len-$i;$k++)
{
if($arr[$k]>$arr[$k+1])
{
$tmp=$arr[$k+1];
$arr[$k+1]=$arr[$k];
$arr[$k]=$tmp;
}
}
}
return $arr;
}

 

二、選擇排序:
http://jingyan.baidu.com/article/f3ad7d0f07516d09c3345b19.html
http://mmm2010.blog.163.com/blog/static/174230348201292273310140/

function select_sort($arr) {
//實現思路 雙重循環完成,外層控制輪數,當前的最小值。內層 控制的比較次數
//$i 當前最小值的位置, 須要參與比較的元素
for($i=0, $len=count($arr); $i<$len-1; $i++) {
//先假設最小的值的位置
$p = $i;
//$j 當前都須要和哪些元素比較,$i 後邊的。
for($j=$i+1; $j<$len; $j++) {
//$arr[$p] 是 當前已知的最小值
if($arr[$p] > $arr[$j]) {
//比較,發現更小的,記錄下最小值的位置;而且在下次比較時,
// 應該採用已知的最小值進行比較。
$p = $j;
}
}
//已經肯定了當前的最小值的位置,保存到$p中。
//若是發現 最小值的位置與當前假設的位置$i不一樣,則位置互換便可
if($p != $i) {
$tmp = $arr[$p];
$arr[$p] = $arr[$i];
$arr[$i] = $tmp;
}
}
//返回最終結果
return $arr;
}

3.快速排序法  

function quick_sort($arr) {
//先判斷是否須要繼續進行
$length = count($arr);
if($length <= 1) {
return $arr;
}
//若是沒有返回,說明數組內的元素個數 多餘1個,須要排序
//選擇一個標尺
//選擇第一個元素
$base_num = $arr[0];
//遍歷 除了標尺外的全部元素,按照大小關係放入兩個數組內
//初始化兩個數組
$left_array = array();//小於標尺的
$right_array = array();//大於標尺的
for($i=1; $i<$length; $i++) {
if($base_num > $arr[$i]) {
//放入左邊數組
$left_array[] = $arr[$i];
} else {
//放入右邊
$right_array[] = $arr[$i];
}
}
//再分別對 左邊 和 右邊的數組進行相同的排序處理方式
//遞歸調用這個函數,並記錄結果
$left_array = quick_sort($left_array);
$right_array = quick_sort($right_array);
//合併左邊 標尺 右邊
return array_merge($left_array, array($base_num), $right_array);
}


四、插入排序法 
http://blog.csdn.net/hijiankang/article/details/9207735

情景描述:
  緊接冒泡排序,每次同窗們都屢試不爽,可是學生愈來愈多了,老師發現每次排完隊,就耽擱了大半節課時了,說道:「咱不用冒泡了,有點OUT了,今天來插入排序」。
這時體育老師擔任起了數學老師的職責,又給同窗們講了種排隊方式--插入排序。
1. 開始以第一位同窗爲基準,由第二個同窗開始向前和第一位同窗比較,個頭高了不動,低了換位
2. 第三個同窗要先和本身前面的第二位同窗比較,若是低了,和第二換位,而後再向前和第一比較,低了再換,不然阻斷,再也不比較
3. 從前日後依次執行步驟2,依次出來一位同窗,每次和本身前面的同窗進行比較,找到一個合適位置插入,其他學生後移
合適位置:前一位同窗等於或低於本身身高,而且後一位同窗高於本身身高
  按照這個方式,同窗們一個個依次找準位置,不再用每次相鄰的都比較,並且找到位置後就沒必要再往前面比較了......

 

插入排序法思路:將要排序的元素插入到已經 假定排序號的數組的指定位置。
function insert_sort($arr) {
//區分 哪部分是已經排序好的
//哪部分是沒有排序的
//找到其中一個須要排序的元素
//這個元素 就是從第二個元素開始,到最後一個元素都是這個須要排序的元素
//利用循環就能夠標誌出來
//i循環控制 每次須要插入的元素,一旦須要插入的元素控制好了,
//間接已經將數組分紅了2部分,下標小於當前的(左邊的),是排序好的序列
for($i=1, $len=count($arr); $i<$len; $i++) {
//得到當前須要比較的元素值。
$tmp = $arr[$i];
//內層循環控制 比較 並 插入
for($j=$i-1;$j>=0;$j--) {
//$arr[$i];//須要插入的元素; $arr[$j];//須要比較的元素
if($tmp < $arr[$j]) {
//發現插入的元素要小,交換位置
//將後邊的元素與前面的元素互換
$arr[$j+1] = $arr[$j];
//將前面的數設置爲 當前須要交換的數
$arr[$j] = $tmp;
} else {
//若是碰到不須要移動的元素
//因爲是已經排序好是數組,則前面的就不須要再次比較了。
break;
}
}
}
//將這個元素 插入到已經排序好的序列內。
//返回
return $arr;
}

 

/**
* 插入排序,默認第一位已經排好序,從第二位開始依次向前比較,肯定本身的位置後插入,即前一位小余或等於當前,且後一位大於當前。
* 插入後,本身新位置後面的元素依次向後移位, 完成一輪插入排序
* @param arr
* @return
*/
public static int[] insertSort(int[] arr) {
int len = arr.length;
for (int i = 1; i < len; i++) {
if (arr[i - 1] > arr[i]) {
int k = arr[i];
int j = i;
while (j > 0 && arr[j - 1] > k) {
arr[j] = arr[j - 1];
j--;
}
arr[j] = k;
}
}
return arr;
}

 


二分查找:

http://www.tuicool.com/articles/2MbAR3q
http://blog.csdn.net/xzjxylophone/article/details/4714326
1,2,3,4,5,6,7
我如今要查找7
我先取出中間數 4
判斷下是否是要找的數字,發現小了
就去右邊查找
而後取出右邊的全部的數
取出她們幾個的中間數 6
發現還小了
繼續找右邊的數組
找到7了 ok了!!!

最差的一種狀況就是這個數字不存在 ====


1 <?php
2 #二分查找
3 function binarySearch(Array $arr, $target) {
4 $low = 0;
5 $high = count($arr) - 1;
6
7 while($low <= $high) {
8 $mid = floor(($low + $high) / 2);
9 #找到元素
10 if($arr[$mid] == $target) return $mid;
11 #中元素比目標大,查找左部
12 if($arr[$mid] > $target) $high = $mid - 1;
13 #重元素比目標小,查找右部
14 if($arr[$mid] < $target) $low = $mid + 1;
15 }
16
17 #查找失敗
18 return false;
19 }
20
21 $arr = array(1, 3, 5, 7, 9, 11);
22 $inx = binarySearch($arr, 1);
23 var_dump($inx);
24 ?>


安全方面:
xss :跨站腳本攻擊
csrf : 跨站請求僞造
Ddos:用不少機器對網址進行請求,把服務器某方面搞掛。
sql注入: 經過關鍵字或者非法字符的注入,實現一些對數據庫一些非正常的操做

最簡單的demo :
在用戶登錄的時候,用戶名和密碼的判斷,密碼後加上 or 1=1

如何防止sql注入:
關鍵字的過濾
pdo預處理
php 配置文件 php.ini 中的 magic_quotes_gpc選項沒有打開,被置爲 off
addslashes stripslashes
mysql_real_escape_string
對一些數據類型作強制的校驗

如何防止xss攻擊?
xss攻擊最簡單的方式就是經過地址欄輸入<script></script>,最簡單的列子咱們在php在使用一個get的a參數的時候,如何客戶端傳過來是<script>alert(1)</script>,
這樣的話就會在咱們的瀏覽器彈出來1,若是是頁面的跳轉,或者是一些其它腳本、病毒的話,可能對咱們網站的安全形成很大的隱患。

最簡單的解決辦法
不要相信客戶端的任何輸入,在程序作嚴格的判斷以及處理
htmlspecialchars進行過濾

csrf :
這個咱們在學curl的時候作的模擬登錄就是跨站請求僞造!!!!
最簡單的大白話就是:
a網站往b網站請求數據。
加個token防止下就好了,簡單,粗暴,有效

Dos和Ddos防止:
阿里雲 高防ip
idc機房
放棄一部分請求不處理。


正則方面的問題:

貪婪模式和非貪婪模式的區別:
貪婪模式匹配到內容以後會繼續向後匹配
非貪婪模式則不回繼續匹配


匹配中文字符的正則表達式: [\u4e00-\u9fa5]
評註:匹配中文還真是個頭疼的事,有了這個表達式就好辦了
匹配雙字節字符(包括漢字在內):[^\x00-\xff]
評註:能夠用來計算字符串的長度(一個雙字節字符長度計2,ASCII字符計1)
匹配空白行的正則表達式:\n\s*\r
評註:能夠用來刪除空白行
匹配HTML標記的正則表達式:<(\S*?)[^>]*>.*?</\1>|<.*? />
評註:網上流傳的版本太糟糕,上面這個也僅僅能匹配部分,對於複雜的嵌套標記依舊無能爲力
匹配首尾空白字符的正則表達式:^\s*|\s*$
評註:能夠用來刪除行首行尾的空白字符(包括空格、製表符、換頁符等等),很是有用的表達式
匹配Email地址的正則表達式:\w+([-+.]\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*
評註:表單驗證時很實用
匹配網址URL的正則表達式:[a-zA-z]+://[^\s]*
評註:網上流傳的版本功能頗有限,上面這個基本能夠知足需求
匹配賬號是否合法(字母開頭,容許5-16字節,容許字母數字下劃線):^[a-zA-Z][a-zA-Z0-9_]{4,15}$
評註:表單驗證時很實用
匹配國內電話號碼:\d{3}-\d{8}|\d{4}-\d{7}
評註:匹配形式如 0511-4405222 或 021-87888822
匹配騰訊QQ號:[1-9][0-9]{4,}
評註:騰訊QQ號從10000開始
匹配中國郵政編碼:[1-9]\d{5}(?!\d)
評註:中國郵政編碼爲6位數字
匹配身份證:\d{15}|\d{18}
評註:中國的身份證爲15位或18位
匹配ip地址:\d+\.\d+\.\d+\.\d+
評註:提取ip地址時有用
匹配特定數字:
^[1-9]\d*$    //匹配正整數
^-[1-9]\d*$   //匹配負整數
^-?[1-9]\d*$   //匹配整數
^[1-9]\d*|0$  //匹配非負整數(正整數 + 0)
^-[1-9]\d*|0$   //匹配非正整數(負整數 + 0)
^[1-9]\d*\.\d*|0\.\d*[1-9]\d*$   //匹配正浮點數
^-([1-9]\d*\.\d*|0\.\d*[1-9]\d*)$  //匹配負浮點數
^-?([1-9]\d*\.\d*|0\.\d*[1-9]\d*|0?\.0+|0)$  //匹配浮點數
^[1-9]\d*\.\d*|0\.\d*[1-9]\d*|0?\.0+|0$   //匹配非負浮點數(正浮點數 + 0)
^(-([1-9]\d*\.\d*|0\.\d*[1-9]\d*))|0?\.0+|0$  //匹配非正浮點數(負浮點數 + 0)
評註:處理大量數據時有用,具體應用時注意修正
匹配特定字符串:
^[A-Za-z]+$  //匹配由26個英文字母組成的字符串
^[A-Z]+$  //匹配由26個英文字母的大寫組成的字符串
^[a-z]+$  //匹配由26個英文字母的小寫組成的字符串
^[A-Za-z0-9]+$  //匹配由數字和26個英文字母組成的字符串
^\w+$  //匹配由數字、26個英文字母或者下劃線組成的字符串

下面是一些特殊字符:
正則表達式中的特殊字符: (學習參考書-<<精通正則表達式>>)
字符
意義:對於字符,一般表示按字面意義,指出接着的字符爲特殊字符,不做解釋。
例如:/b/匹配字符'b',經過在b 前面加一個反斜槓,也就是/b/,則該字符變成特殊字符,表示
匹配一個單詞的分界線。
或者:
對於幾個字符,一般說明是特殊的,指出緊接着的字符不是特殊的,而應該按字面解釋。
例如:*是一個特殊字符,匹配任意個字符(包括0個字符);例如:/a*/意味匹配0個或多個a。
爲了匹配字面上的*,在a前面加一個反斜槓;例如:/a*/匹配'a*'。

字符^
意義:表示匹配的字符必須在最前邊。
例如:/^A/不匹配"an A,"中的'A',但匹配"An A."中最前面的'A'。

字符$
意義:與^相似,匹配最末的字符。
例如:/t$/不匹配"eater"中的't',但匹配"eat"中的't'。

字符*
意義:匹配*前面的字符0次或n次。
例如:/bo*/匹配"A ghost booooed"中的'boooo'或"A bird warbled"中的'b',但不匹配"A goat g
runted"中的任何字符。

字符+
意義:匹配+號前面的字符1次或n次。等價於{1,}。
例如:/a+/匹配"candy"中的'a'和"caaaaaaandy."中的全部'a'。

字符?
意義:匹配?前面的字符0次或1次。
例如:/e?le?/匹配"angel"中的'el'和"angle."中的'le'。

字符.
意義:(小數點)匹配除換行符外的全部單個的字符。
例如:/.n/匹配"nay, an apple is on the tree"中的'an'和'on',但不匹配'nay'。


字符(x)
意義:匹配'x'並記錄匹配的值。
例如:/(foo)/匹配和記錄"foo bar."中的'foo'。匹配子串能被結果數組中的素[1], ..., [n] 返
回,或被RegExp對象的屬性$1, ..., $9返回。

字符x|y
意義:匹配'x'或者'y'。
例如:/green|red/匹配"green apple"中的'green'和"red apple."中的'red'。

字符{n}
意義:這裏的n是一個正整數。匹配前面的n個字符。
例如:/a{2}/不匹配"candy,"中的'a',但匹配"caandy," 中的全部'a'和"caaandy."中前面的兩個
'a'。

字符{n,}
意義:這裏的n是一個正整數。匹配至少n個前面的字符。
例如:/a{2,}不匹配"candy"中的'a',但匹配"caandy"中的全部'a'和"caaaaaaandy."中的全部'a'

字符{n,m}
意義:這裏的n和m都是正整數。匹配至少n個最多m個前面的字符。
例如:/a{1,3}/不匹配"cndy"中的任何字符,但匹配 "candy,"中的'a',"caandy," 中的前面兩個
'a'和"caaaaaaandy"中前面的三個'a',注意:即便"caaaaaaandy" 中有不少個'a',但只匹配前面的三
個'a'即"aaa"。

字符[xyz]
意義:一字符列表,匹配列出中的任一字符。你能夠經過連字符-指出一個字符範圍。
例如:[abcd]跟[a-c]同樣。它們匹配"brisket"中的'b'和"ache"中的'c'。

字符[^xyz]
意義:一字符補集,也就是說,它匹配除了列出的字符外的全部東西。 你可使用連字符-指出一
字符範圍。
例如:[^abc]和[^a-c]等價,它們最先匹配"brisket"中的'r'和"chop."中的'h'。

字符
意義:匹配一個空格(不要與b混淆)

字符b
意義:匹配一個單詞的分界線,好比一個空格(不要與混淆)
例如:/bnw/匹配"noonday"中的'no',/wyb/匹配"possibly yesterday."中的'ly'。

字符B
意義:匹配一個單詞的非分界線
例如:/wBn/匹配"noonday"中的'on',/yBw/匹配"possibly yesterday."中的'ye'。

字符cX
意義:這裏的X是一個控制字符。匹配一個字符串的控制字符。
例如:/cM/匹配一個字符串中的control-M。

字符d
意義:匹配一個數字,等價於[0-9]。
例如:/d/或/[0-9]/匹配"B2 is the suite number."中的'2'。

字符D
意義:匹配任何的非數字,等價於[^0-9]。
例如:/D/或/[^0-9]/匹配"B2 is the suite number."中的'B'。

字符f
意義:匹配一個表單符

字符n
意義:匹配一個換行符

字符r
意義:匹配一個回車符

字符s
意義:匹配一個單個white空格符,包括空格,tab,form feed,換行符,等價於[ fnrtv]。
例如:/sw*/匹配"foo bar."中的' bar'。

字符S
意義:匹配除white空格符之外的一個單個的字符,等價於[^ fnrtv]。
例如:/S/w*匹配"foo bar."中的'foo'。

字符t
意義:匹配一個製表符

字符v
意義:匹配一個頂頭製表符

字符w
意義:匹配全部的數字和字母以及下劃線,等價於[A-Za-z0-9_]。
例如:/w/匹配"apple,"中的'a',"$5.28,"中的'5'和"3D."中的'3'。

字符W
意義:匹配除數字、字母外及下劃線外的其它字符,等價於[^A-Za-z0-9_]。
例如:/W/或者/[^$A-Za-z0-9_]/匹配"50%."中的'%'。

字符n
意義:這裏的n是一個正整數。匹配一個正則表達式的最後一個子串的n的值(計數左圓括號)。


php函數方面的問題:

一、數組函數

array_key_exists 判斷key是否存在
is_array 判斷是不是一個數組
in_array 判斷給定的值是否在數據出現
array_count_values 判斷值出現的次數
array_search 數組查找
array_merge 數組合並
array_map 對數組每一個元素使用用戶自定義的函數
array_change_case 改變數組key的大小寫
sort數組排序
array_push 在數組尾部插入一個或者多個元素
array_pop 彈出數組最後一個元素
array_unshift 數組開頭插入多個元素
array_shift 彈出數組第一個元素
implode 數組轉字符串
shuffle 打亂數組的排序
array_rand 隨機從數組去處多個單元
array_chunk 數組分割位新的數組
array_diff 差集
array_inestsert 交集
array_flip 交換鍵值
array_keys 返回數組全部鍵
count 計算數組長度

二、字符串函數
addcslashes — 爲字符串裏面的部分字符添加反斜線轉義字符
addslashes — 用指定的方式對字符串裏面的字符進行轉義
bin2hex — 將二進制數據轉換成十六進制表示
chop — rtrim() 的別名函數
chr — 返回一個字符的ASCII碼
chunk_split — 按必定的字符長度將字符串分割成小塊
convert_cyr_string — 將斯拉夫語字符轉換爲別的字符
convert_uudecode — 解密一個字符串
convert_uuencode — 加密一個字符串
count_chars — 返回一個字符串裏面的字符使用信息
crc32 — 計算一個字符串的crc32多項式
crypt — 單向散列加密函數
echo — 用以顯示一些內容
explode — 將一個字符串用分割符轉變爲一數組形式
fprintf — 按照要求對數據進行返回,並直接寫入文檔流
get_html_translation_table — 返回能夠轉換的HTML實體
hebrev — 將Hebrew編碼的字符串轉換爲可視的文本
hebrevc — 將Hebrew編碼的字符串轉換爲可視的文本
html_entity_decode — htmlentities ()函數的反函數,將HTML實體轉換爲字符
htmlentities — 將字符串中一些字符轉換爲HTML實體
htmlspecialchars_decode —htmlspecialchars()函數的反函數,將HTML實體轉換爲字符
htmlspecialchars — 將字符串中一些字符轉換爲HTML實體
implode — 將數組用特定的分割符轉變爲字符串
join — 將數組轉變爲字符串,implode()函數的別名
levenshtein — 計算兩個詞的差異大小
localeconv — 獲取數字相關的格式定義
ltrim — 去除字符串左側的空白或者指定的字符
md5_file — 將一個文件進行MD5算法加密
md5 — 將一個字符串進行MD5算法加密
metaphone — 判斷一個字符串的發音規則
money_format — 按照參數對數字進行格式化的輸出
nl_langinfo — 查詢語言和本地信息
nl2br — 將字符串中的換行符「\n」替換成「<br/>」
number_format — 按照參數對數字進行格式化的輸出
ord — 將一個ASCII碼轉換爲一個字符
parse_str — 把必定格式的字符串轉變爲變量和值
print — 用以輸出一個單獨的值
printf — 按照要求對數據進行顯示
quoted_printable_decode — 將一個字符串加密爲一個8位的二進制字符串
quotemeta — 對若干個特定字符進行轉義
rtrim — 去除字符串右側的空白或者指定的字符
setlocale — 設置關於數字,日期等等的本地格式
sha1_file — 將一個文件進行SHA1算法加密
sha1 — 將一個字符串進行SHA1算法加密
similar_text — 比較兩個字符串,返回系統認爲的類似字符個數
soundex — 判斷一個字符串的發音規則
sprintf — 按照要求對數據進行返回,可是不輸出
sscanf — 能夠對字符串進行格式化
str_ireplace — 像str_replace()函數同樣匹配和替換字符串,可是不區分大小寫
str_pad — 對字符串進行兩側的補白
str_repeat — 對字符串進行重複組合
str_replace — 匹配和替換字符串
str_rot13 — 將字符串進行ROT13加密處理
str_shuffle — 對一個字符串裏面的字符進行隨機排序
str_split — 將一個字符串按照字符間距分割爲一個數組
str_word_count — 獲取字符串裏面的英文單詞信息
strcasecmp — 對字符串進行大小比較,不區分大小寫
strchr — 經過比較返回一個字符串的部分strstr()函數的別名
strcmp — 對字符串進行大小比較
strcoll – 根據本地設置對字符串進行大小比較
strcspn — 返回字符連續非匹配長度的值
strip_tags — 去除一個字符串裏面的HTML和PHP代碼
stripcslashes — 反轉義addcslashes()函數轉義處理過的字符串
stripos — 查找並返回首個匹配項的位置,匹配不區分大小寫
stripslashes — 反轉義addslashes()函數轉義處理過的字符串
stristr — 經過比較返回一個字符串的部分,比較時不區分大小寫
strlen — 獲取一個字符串的編碼長度
strnatcasecmp — 使用天然排序法對字符串進行大小比較,不區分大小寫
strnatcmp — 使用天然排序法對字符串進行大小比較
strncasecmp — 對字符串的前N個字符進行大小比較,不區分大小寫
strncmp — 對字符串的前N個字符進行大小比較
strpbrk — 經過比較返回一個字符串的部分
strpos — 查找並返回首個匹配項的位置
strrchr — 經過從後往前比較返回一個字符串的部分
strrev — 將字符串裏面的全部字母反向排列
strripos — 從後往前查找並返回首個匹配項的位置,匹配不區分大小寫
strrpos – 從後往前查找並返回首個匹配項的位置
strspn — 匹配並返回字符連續出現長度的值
strstr — 經過比較返回一個字符串的部分
strtok — 用指定的若干個字符來分割字符串
strtolower — 將字符串轉變爲小寫
strtoupper –將字符串轉變爲大寫
strtr — 對字符串比較替換
substr_compare — 對字符串進行截取後的比較
substr_count — 計算字符串中某字符段的出現次數
substr_replace — 對字符串中的部分字符進行替換
substr — 對字符串進行截取
trim — 去除字符串兩邊的空白或者指定的字符
ucfirst — 將所給字符串的第一個字母轉換爲大寫
ucwords — 將所給字符串的每個英文單詞的第一個字母變成大寫
vfprintf — 按照要求對數據進行返回,並直接寫入文檔流
vprintf — 按照要求對數據進行顯示
vsprintf — 按照要求對數據進行返回,可是不輸出
wordwrap — 按照必定的字符長度分割字符串

 

關於代碼規範如何說?

咱們在寫接口的時候寫了一個統一的驗證和返回

要求每一個文件必須有本身的註釋、每一個類都有本身的註釋、每一個方法都必須有註釋 、對於不肯定的需求或者後期可能遇到的問題 必須加上 todo

關鍵邏輯必須寫上註釋

在調用外部接口不能在程序寫死,必須單獨本身建議一個配置文件,方便後期修改

數據庫操做必須寫在model裏邊,不容許在C層寫數據庫操做。

變量名必須能報清楚的表達本身的意思。

寫接口以前必須搞定接口文檔。

私有的方法必須加上 _ [ 重要 ,顯得本身也是老司機]

 

類文件都是以.class.php爲後綴(這裏是指的ThinkPHP內部使用的類庫文件,不表明外部加載的類庫文件),使用駝峯法命名,而且首字母大寫,例如 DbMysql.class.php;

類的命名空間地址和所在的路徑地址一致,例如 Home\Controller\UserController類所在的路徑應該是 Application/Home/Controller/UserController.class.php;
確保文件的命名和調用大小寫一致,是因爲在類Unix系統上面,對大小寫是敏感的(而ThinkPHP在調試模式下面,即便在Windows平臺也會嚴格檢查大小寫);
類名和文件名一致(包括上面說的大小寫一致),例如 UserController類的文件命名是UserController.class.php, InfoModel類的文件名是InfoModel.class.php,
 而且不一樣的類庫的類命名有必定的規範;

函數、配置文件等其餘類庫文件以外的通常是以.php爲後綴(第三方引入的不作要求);

函數的命名使用小寫字母和下劃線的方式,例如 get_client_ip;

方法的命名使用駝峯法,而且首字母小寫或者使用下劃線「_」,例如 getUserName,_parseType,一般下劃線開頭的方法屬於私有方法;
屬性的命名使用駝峯法,而且首字母小寫或者使用下劃線「_」,例如 tableName、_instance,一般下劃線開頭的屬性屬於私有屬性;
以雙下劃線「__」打頭的函數或方法做爲魔法方法,例如 __call 和 __autoload;

常量以大寫字母和下劃線命名,例如 HAS_ONE和 MANY_TO_MANY;

配置參數以大寫字母和下劃線命名,例如HTML_CACHE_ON;

語言變量以大寫字母和下劃線命名,例如MY_LANG,如下劃線打頭的語言變量
一般用於系統語言變量,例如 _CLASS_NOT_EXIST_;

對變量的命名沒有強制的規範,能夠根據團隊規範來進行;

ThinkPHP的模板文件默認是以.html 爲後綴(能夠經過配置修改);

數據表和字段採用小寫加下劃線方式命名,並注意字段名不要如下劃線開頭,例
如 think_user 表和 user_name字段是正確寫法,相似 _username 這樣的數據表字段可能會被過濾。


tp底層看過沒有?


一、看過框架的底層沒有?
看過tp的數據庫驅動相關。 關於配置數據庫方面的,在配置文件配置就直接可使用各類數據庫類型,本身簡單看了下,主要就是經過一個driver(驅動類)來判斷當前鏈接類
型,而後調用對於的數據庫操做類。
ps:若是是要咱們本身實現的話,能夠藉助接口,每一個數據庫的操做類都須要集成一個接口,而後根據具體的配置去調用每一個操做類。 就算後期我修改了數據庫的類型,也不
會致使程序須要改動。

二、看過tp的cache類,和數據庫相似,修改過redis的cache類,由於tp的redis操做類不支持認證。
主要就是在redis操做類添加了個認證
$this->handler = new \Redis;
$options['timeout'] === false ?
$this->handler->$func($options['host'], $options['port']) :
$this->handler->$func($options['host'], $options['port'], $options['timeout']);
$this -> handler->auth( C(‘REDIS_AUTH_KEY’) );

三、看過tp的處理異常類
路徑 ThinkPHP/library/Think/Think.class.php

主要使用的是php自帶的錯誤處理相關函數

register_shutdown_function 定義PHP程序執行完成後執行的函數
set_error_handler 設置用戶自定義的錯誤處理程序
set_exception_handler 設置本身的異常處理機制

藉助 get_last_error獲取最後一次報錯的信息
根據報錯級別能夠自定義寫日誌
這個地方咱們在作接口的時候紀錄了一些錯誤日誌,幫助咱們排查一些問題。
若是要看文件加載以及調用關係能夠藉助 print_debug_backtrace獲取文件加載的順序

// 註冊AUTOLOAD方法 spl_autoload_register('Think\Think::autoload'); // 設定錯誤和異常處理 register_shutdown_function('Think\Think::fatalError'); set_error_handler('Think\Think::appError'); set_exception_handler('Think\Think::appException');

相關文章
相關標籤/搜索