首頁  >  文章  >  後端開發  >  PHP面試題目整理分享

PHP面試題目整理分享

小云云
小云云原創
2018-03-27 11:14:284383瀏覽

本文主要跟大家分享PHP面試題目整理分享,希望能幫助大家更順利的面試。

伺服器方面

1、nginx平滑重啟

nginx 運行新的工作進程並從容關閉舊的工作進程,通知工作進程關閉監聽套接字,但是繼續為當前連接的客戶提供服務。所有的客戶端的服務完成後,舊的工作進程會被
關閉。如果新的設定檔套用失敗,nginx 將繼續使用舊的設定檔進行工作。
說簡單點就是 nginx會繼續處理之前的請求,並且啟動一個新的進程來處理新的請求,舊的進程處理完成之後會被kill。

2、取得檔案後10行。
tail -10 a.log

3、查看佔用系統資源比較多的進程
     top  
    ps:輸完top指令之後,按1可以看內存以及cpu使用情況

3、查看關鍵字出現函數
grep -n '我是要找的關鍵字' a.txt | cut  -d “:” - f1

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


4、在/root/目錄下搜尋有關鍵字「www」的文件,在終端機下執行指令:
find /root/ –type f | xargs grep “www

#5、統計檔行數
wc -l  a.txt

# 統計數字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

6、即時監控一個檔案
tail -f a.log

#7、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

8、在編譯完成的php,增加新的擴充
------ -----------------------------------
排版安裝
1、找到php的源碼目錄
2、跳到EXT目錄下邊
3、執行phpize產生configure檔
4、 ./configure --with-php-config=/usr/local/php/bin/php-config
5、編譯make
6、編譯安裝make install
7、修改php.ini extension=/usr/local/***.so
8、重啟php-fpm

YUM安裝:
1、去PHP的官網下載原始碼(htpp://pecl.php.net)
2、解壓縮檔
3、執行phpize產生configure檔
4、 ./ configure --with-php-config=/usr/local/php/bin/php-config
5、編譯make
6、編譯安裝make install
7、修改php.ini extension=/usr /local/***.so
8、重啟php-fpm
--------------------------------」 -----------
php最佳化nginx最佳化mysql最佳化

php最佳化:
1、將類別的方法定義為static。
2、盡量使用單引號。
3、修改php-fpm進程數。
4、修改單一腳本最大可使用記憶體。
5、大的陣列使用完後要及時釋放。
6、循環的時候,制定最大循環次數
7、不使用@屏蔽錯誤
8、盡量採用大量的PHP 內建函數
9、使用require代替require_once

# nginx最佳化:
1、修改nginx的子程序數。 [ 最多65535 ]
2、開啟靜態快取
3、修改主行程數。建議依照cpu 數目來指定,一般為它的倍數(如,2個四核心的cpu計為8)
4、開啟gzip輸出  [ 開啟gzip,ob函數就不能用了]
5、keepalive_timeout設定連線逾時時間

mysql最佳化:
1、避免子查詢
2、有順序的讀取
3、避免重複的讀寫
4、設定自增id
5、避免使用select *
6、合理設定欄位類型
7、讀寫分離
8、分割區、分錶
9、建立適當的索引
10、避免使用耗費資源的操作null
11、不要使用rand()
12、盡量不要使用or  查詢
13、查詢一筆資料的時候加上LIMIT 1
14、開啟查詢快取
15、前期對資料進行合理的評估,進行分區、分錶
16、避免使用%前綴的模糊查詢
17、避免使用mysql自帶函數
18、使用多從解決查詢慢的問題

秒殺如何實現?

我們做的秒殺並發量就是十幾萬、下邊的版本是十幾萬的:

1、專門對秒殺伺服器 [ps:量大的話這麼說,如果小的話就不用了]
2、產生靜態頁面。 [ ps:如果還很大的可以把這個檔案放在 cdn上 ]
3.倒數計時以及庫存從服務端獲取[ 一段時間內只獲取一次,倒數計時結束之後會請求下服務端,是否已經開始]
4、把要秒殺的資料庫存放到redis中  [ key value ] stock= 10
5、設定一個redis隊列  [ 使用list做隊列] lpop rpush
6、用戶在請求的時候,判斷用戶是否參與過秒殺,沒有參加過把用戶資料寫入隊列中,同時庫存減1 ,參加過就提示已經參加過
    ps:這塊用到了redid的原子性操作、以及事務multi 和watch
   redis樂觀鎖 cas  ====  就是設定之前判斷下這個值有沒有改變
7、庫存減0就不能進行秒殺
8、非同步腳本處理佇列資料[ 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:每次搶購活動的時候用一套新的驗證碼?
驗證碼這個東東,屬於圖靈測試嘛,只要測試方法好,並且盡可能保證每次產生的驗證信息從未出現過且無規律,就是好的驗證碼啦。

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

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

假設有1kw個身分證號,以及他們對應的資料。身分證號碼可能會重複,要求找出出現次數最多的身分證字號。
 
有一個1G大小的一個文件,裡面每一行是一個詞,詞的大小不超過16字節,記憶體限制大小是1M。傳回頻數最高的100個字。

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

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

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;
}

2、選擇排序:

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);
}

4、插入排序法 
情境說明:
  緊接著冒泡排序,每次同學們都屢試不爽,但是學生越來越多了,老師發現每次排完隊,就耽擱了大半節課時了,說道:「咱不用冒泡了,有點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;
    }


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攻击最简单的方式就是通过地址栏输入3f1c4e4b6b16bbbd69b2ee476dc4f83a2cacc6d41bbb37262a98f745aa00fbf0,最简单的列子我们在php在使用一个get的a参数的时候,如何客户端传过来是3f1c4e4b6b16bbbd69b2ee476dc4f83aalert(1)2cacc6d41bbb37262a98f745aa00fbf0,
这样的话就会在我们的浏览器弹出来1,如果是页面的跳转,或者是一些其它脚本、病毒的话,可能对我们网站的安全造成很大的隐患。

最简单的解决办法
不要相信客户端的任何输入,在程序做严格的判断以及处理
htmlspecialchars进行过滤

csrf :
这个我们在学curl的时候做的模拟登陆就是跨站请求伪造!!!!
最简单的大白话就是:
a网站往b网站请求数据。
加个token防止下就行了,简单,粗暴,有效

Dos和Ddos防止:
阿里云 高防ip
idc机房
放弃一部分请求不处理。


正则方面的问题:

贪婪模式和非贪婪模式的区别:
贪婪模式匹配到内容之后会继续向后匹配
非贪婪模式则不回继续匹配


匹配中文字符的正则表达式: [\u4e00-\u9fa5]
评注:匹配中文还真是个头疼的事,有了这个表达式就好办了
匹配双字节字符(包括汉字在内):[^\x00-\xff]
评注:可以用来计算字符串的长度(一个双字节字符长度计2,ASCII字符计1)
匹配空白行的正则表达式:\n\s*\r
评注:可以用来删除空白行
匹配HTML标记的正则表达式:706b83c79d2c696ac46a98098db7b11b]*>.*?c0f8603dd44f0db5dcc943cf687721b3|7ced4b295831648a0fce6ecb53f5fd4b
评注:网上流传的版本太糟糕,上面这个也仅仅能匹配部分,对于复杂的嵌套标记依旧无能为力
匹配首尾空白字符的正则表达式:^\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函數方面的問題:

1、陣列函數

# 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 計算陣列長度

2、字串函數
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」替換成「076402276aae5dbec7f672f8f4e5cc81」
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底层看过没有?


1、看过框架的底层没有?
    看过tp的数据库驱动相关。 关于配置数据库方面的,在配置文件配置就直接可以使用各种数据库类型,自己简单看了下,主要就是通过一个driver(驱动类)来判断当前连接类
型,然后调用对于的数据库操作类。
    ps:如果是要我们自己实现的话,可以借助接口,每个数据库的操作类都需要集成一个接口,然后根据具体的配置去调用每个操作类。 就算后期我修改了数据库的类型,也不
会导致程序需要改动。

2、看过tp的cache类,和数据库类似,修改过redis的cache类,因为tp的redis操作类不支持认证。
  主要就是在redis操作类添加了个认证

$this->handler  = new \Redis;
        $options[&#39;timeout&#39;] === false ?
            $this->handler->$func($options[&#39;host&#39;], $options[&#39;port&#39;]) :
            $this->handler->$func($options[&#39;host&#39;], $options[&#39;port&#39;], $options[&#39;timeout&#39;]);
            $this -> handler->auth( C(‘REDIS_AUTH_KEY’) );

3、看过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(&#39;Think\Think::autoload&#39;);      
      // 设定错误和异常处理
      register_shutdown_function(&#39;Think\Think::fatalError&#39;);
      set_error_handler(&#39;Think\Think::appError&#39;);
      set_exception_handler(&#39;Think\Think::appException&#39;);

4、简单看了下tp的命名空间自动记载
框架下的核心类都包含进来了,其他的事借助 spl_register_autoload实现。

以上是PHP面試題目整理分享的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述:
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn