1. 程式人生 > 實用技巧 >PHP核心技術面試題,跳槽必備!

PHP核心技術面試題,跳槽必備!

1 oop是什麼?

答:oop是面向物件程式設計,面向物件程式設計是一種計算機程式設計架構,OOP 的一條基本原則是計算機程式是由單個能夠起到子程式作用的單元或物件組合而成。

OOP具有三大特點

1、封裝性:也稱為資訊隱藏,就是將一個類的使用和實現分開,只保留部分介面和方法與外部聯絡,或者說只公開了一些供開發人員使用的方法。於是開發人員只 需要關注這個類如何使用,而不用去關心其具體的實現過程,這樣就能實現MVC分工合作,也能有效避免程式間相互依賴,實現程式碼模組間鬆藕合。

2、繼承性:就是子類自動繼承其父級類中的屬性和方法,並可以新增新的屬性和方法或者對部分屬性和方法進行重寫。繼承增加了程式碼的可重用性。PHP只支援單繼承,也就是說一個子類只能有一個父類。

3、多型性:子類繼承了來自父級類中的屬性和方法,並對其中部分方法進行重寫。於是多個子類中雖然都具有同一個方法,但是這些子類例項化的物件呼叫這些相同的方法後卻可以獲得完全不同的結果,這種技術就是多型性。多型性增強了軟體的靈活性。

1、易維護

採用面向物件思想設計的結構,可讀性高,由於繼承的存在,即使改變需求,那麼維護也只是在區域性模組,所以維護起來是非常方便和較低成本的。

2、質量高

在設計時,可重用現有的,在以前的專案的領域中已被測試過的類使系統滿足業務需求並具有較高的質量。

3、效率高

在軟體開發時,根據設計的需要對現實世界的事物進行抽象,產生類。使用這樣的方法解決問題,接近於日常生活和自然的思考方式,勢必提高軟體開發的效率和質量。

4、易擴充套件

由於繼承、封裝、多型的特性,自然設計出高內聚、低耦合的系統結構,使得系統更靈活、更容易擴充套件,而且成本較低。

2 合併兩個陣列有幾種方式,試比較它們的異同

方式:

1、array_merge()

2、’+’

3、array_merge_recursive

異同:

array_merge 簡單的合併陣列

array_merge_recursive 合併兩個陣列,如果陣列中有完全一樣的資料,將它們遞迴合併

array_combine 和 ‘+’ :合併兩個陣列,前者的值作為新陣列的鍵

3 PHP的is_writeable()函式存在Bug,無法準確判斷一個目錄/檔案是否可寫,請寫一個函式來判斷目錄/檔案是否絕對可寫

答:其中bug存在兩個方面,

1、在windowns中,當檔案只有只讀屬性時,is_writeable()函式才返回false,當返回true時,該檔案不一定是可寫的。

如果是目錄,在目錄中新建檔案並通過開啟檔案來判斷;

如果是檔案,可以通過開啟檔案(fopen),來測試檔案是否可寫。

2、在Unix中,當php配置檔案中開啟safe_mode時(safe_mode=on),is_writeable()同樣不可用。

讀取配置檔案是否safe_mode是否開啟。

/**
* Tests for file writability
*
* is_writable() returns TRUE on Windows servers when you really can't write to
* the file, based on the read-only attribute. is_writable() is also unreliable
* on Unix servers if safe_mode is on.
*
* @access   private
* @return   void
*/

if ( ! function_exists('is_really_writable'))
{
    function is_really_writable($file){

    // If we're on a Unix server with safe_mode off we call is_writable
    if (DIRECTORY_SEPARATOR == '/' AND @ini_get("safe_mode") == FALSE){
        return is_writable($file);
    }

    // For windows servers and safe_mode "on" installations we'll actually
    // write a file then read it. Bah...
    if (is_dir($file)){

        $file = rtrim($file, '/').'/'.md5(mt_rand(1,100).mt_rand(1,100));

        if (($fp = @fopen($file, FOPEN_WRITE_CREATE)) === FALSE){
            return FALSE;
        }

        fclose($fp);
        @chmod($file, DIR_WRITE_MODE);
        @unlink($file);
        return TRUE;

    } elseif ( ! is_file($file) OR ($fp = @fopen($file, FOPEN_WRITE_CREATE)) === FALSE) {

        return FALSE;
    }

    fclose($fp);
    return TRUE;

    }

}

4 PHP的垃圾收集機制是怎樣的?

PHP可以自動進行記憶體管理,清除不再需要的物件。PHP使用了引用計數(reference counting)這種單純的垃圾回收(garbage collection)機制。每個物件都內含一個引用計數器,每個reference連線到物件,計數器加1。當reference離開生存空間或被設為NULL,計數器減1。當某個物件的引用計數器為零時,PHP知道你將不再需要使用這個物件,釋放其所佔的記憶體空間。

5 寫一個函式,儘可能高效的,從一個標準url裡取出檔案的副檔名,

例如:http://www.startphp.cn/abc/de/fg.php?id=1需要取出php或.php

<?php

    // 方案一
    function getExt1($url){

        $arr = parse_url($url);
        //Array ( [scheme] => http [host] => www.startphp.cn [path] => /abc/de/fg.php [query] => id=1 )

        $file = basename($arr['path']);
        $ext = explode('.', $file);
        return $ext[count($ext)-1];
    }



    // 方案二
    function getExt2($url){

        $url = basename($url);
        $pos1 = strpos($url,'.');
        $pos2 = strpos($url,'?');

        if (strstr($url,'?')) {
            return substr($url,$pos1+1,$pos2-$pos1-1);

        } else {
            return substr($url,$pos1);
        }
    }

    $path = "http://www.startphp.cn/abc/de/fg.php?id=1";
    echo getExt1($path);
    echo "<br />";
    echo getExt2($path);

?>

6 使用正則表示式提取一段標識語言(html或xml)程式碼段中指定標籤的指定屬性值(需考慮屬性值對不規則的情況,如大小寫不敏感,屬性名值與等號間有空格等)。此處假設需提取test標籤的attr屬性值,請自行構建包含該標籤的串(騰訊)

如下:

<?php
    header("content-type:text/html;charset=utf-8");

    function getAttrValue($str,$tagName,$attrName){
        $pattern1="/<".$tagName."(s+w+s*=s*(['"]?)([^'"]*)())*s+".$attrName."s*=s*(['"]?)([^'"]*)()(s+w+s*=s*(['"]?)([^'"]*)(9))*s*>/i";

        $arr=array();
        $re=preg_match($pattern1,$str,$arr);

        if($re){
            echo"<br/>$arr[6]={$arr[6]}";
        }else{
            echo"<br/>沒找到。";
        }

    }

    // 示例

    $str1="<test attr='ddd'>";
    getAttrValue($str1,"test","attr");//找test標籤中attr屬性的值,結果為ddd

    $str2="<test2 attr='ddd'attr2='ddd2't1="t1 value"t2='t2 value'>";

    getAttrValue($str2,"test2","t1");//找test2標籤中t1屬性的值,結果為t1 value

?>

7 php中WEB上傳檔案的原理是什麼,如何限制上傳檔案的大小?

上傳檔案的表單使用post方式,並且要在form中新增enctype='multipart/form-data'。

一般可以加上隱藏域:,位置在file域前面。

value的值是上傳檔案的客戶端位元組限制。可以避免使用者在花時間等待上傳大檔案之後才發現檔案過大上傳失敗的麻煩。

使用file檔案域來選擇要上傳的檔案,當點選提交按鈕之後,檔案會被上傳到伺服器中的臨時目錄,在指令碼執行結束時會被銷燬,所以應該在指令碼結束之前,將其移動到伺服器上的某個目錄下,可以通過函式move_uploaded_file()來移動臨時檔案,要獲取臨時檔案的資訊,使用$_FILES。

限制上傳檔案大小的因素有:

客戶端的隱藏域MAX_FILE_SIZE的數值(可以被繞開)。

伺服器端的upload_max_filesize,post_max_size和memory_limit。這幾項不能夠用指令碼來設定。

自定義檔案大小限制邏輯。即使伺服器的限制是能自己決定,也會有需要個別考慮的情況。所以這個限制方式經常是必要的。

8 請說明 PHP 中傳值與傳引用的區別,什麼時候傳值什麼時候傳引用?

按值傳遞:函式範圍內對值的任何改變在函式外部都會被忽略

按引用傳遞:函式範圍內對值的任何改變在函式外部也能反映出這些修改

優缺點:按值傳遞時,php必須複製值。特別是對於大型的字串和物件來說,這將會是一個代價很大的操作。按引用傳遞則不需要複製值,對於效能提高很有好處。(優缺點會考到)

9 MySQL資料庫中的欄位型別varchar和char的主要區別是什麼?

Varchar是變長,節省儲存空間,char是固定長度。查詢效率要char型快,因為varchar是非定長,必須先查詢長度,然後進行資料的提取,比char定長型別多了一個步驟,所以效率低一些。

10 靜態化如何實現的?偽靜態如何實現?

1、 靜態化指的是頁面靜態化,也即生成實實在在的靜態檔案,也即不需要查詢資料庫就可以直接從檔案中獲取資料,指的是真靜態。

實現方式主要有兩種:一種是我們在新增資訊入庫的時候就生成的靜態檔案,也稱為模板替換技術。一種是使用者在訪問我們的頁面時先判斷是否有對應的快取檔案存在,如果存在就讀快取,不存在就讀資料庫,同時生成快取檔案。

2、偽靜態不是真正意義上的靜態化,之所以使用偽靜態,主要是為了SEO推廣,搜尋引擎對動態的檔案獲取難度大,不利於網站的推廣。實習原理是基於Apache或Nginx的rewrite機智

主要有兩種方式:一種是直接在配置虛擬機器的位置配置偽靜態,這個每次修改完成後需要重啟web伺服器。另一種採用分散式的,可以在網站的根目錄上建立.htaccess的檔案,在裡面配置相應的重寫規則來實現偽靜態,這種每次重寫時不需要重啟web伺服器,且結構上比較清晰。

11 如何處理負載,高併發?

1、HTML靜態化

效率最高、消耗最小的就是純靜態化的html頁面,所以我們儘可能使我們的 網站上的頁面採用靜態頁面來實現,這個最簡單的方法其實也是最有效的方法。

2、圖片伺服器分離

把圖片單獨儲存,儘量減少圖片等大流量的開銷,可以放在一些相關的平臺上,如七牛等

3、資料庫叢集和庫表雜湊及快取

資料庫的併發連線為100,一臺資料庫遠遠不夠,可以從讀寫分離、主從複製,資料庫叢集方面來著手。另外儘量減少資料庫的訪問,可以使用快取資料庫如memcache、redis。

4、映象:

儘量減少下載,可以把不同的請求分發到多個映象端。

5、負載均衡:

Apache的最大併發連線為1500,只能增加伺服器,可以從硬體上著手,如F5伺服器。當然硬體的成本比較高,我們往往從軟體方面著手。

12 PHP7的新特性?

標量型別宣告:PHP 7 中的函式的形參型別宣告可以是標量了。在 PHP 5 中只能是類名、介面、array 或者 callable (PHP 5.4,即可以是函式,包括匿名函式),現在也可以使用 string、int、float和 bool 了。

返回值型別宣告:增加了對返回型別宣告的支援。類似於引數型別宣告,返回型別宣告指明瞭函式返回值的型別。可用的型別與引數宣告中可用的型別相同。NULL 合併運算子:由於日常使用中存在大量同時使用三元表示式和 isset()的情況,NULL 合併運算子使得變數存在且值不為NULL, 它就會返回自身的值,否則返回它的第二個運算元。

use 加強:從同一 namespace 匯入的類、函式和常量現在可以通過單個 use 語句 一次性匯入了 匿名類:現在支援通過new class 來例項化一個匿名類

13 常見的 PHP 安全性攻擊 SQL注入:

使用者利用在表單欄位輸入SQL語句的方式來影響正常的SQL執行。

防止:使用mysql_real_escape_string()過濾資料 手動檢查每一資料是否為正確的資料型別 使用預處理語句並繫結變數 引數化SQL:是指在設計與資料庫連結並訪問資料時,在需要填入數值或資料的地方,使用引數 (Parameter) 來給值,用@或?來表示引數。

XSS攻擊 :跨站點指令碼攻擊,由使用者輸入一些資料到你的網站,其中包括客戶端指令碼(通常JavaScript)。如果你沒有過濾就輸出資料到另一個web頁面,這個指令碼將被執行。

防止:為了防止XSS攻擊,使用PHP的htmlentities()函式過濾再輸出到瀏覽器。

CSRF:跨站點請求偽造,是指一個頁面發出的請求,看起來就像是網站的信任使用者,但是是偽造的

防止:一般來說,確保使用者來自你的表單,並且匹配每一個你傳送出去的表單。有兩點一定要記住:對使用者會話採用適當的安全措施,例如:給每一個會話更新id和使用者使用SSL。生成另一個一次性的令牌並將其嵌入表單,儲存在會話中(一個會話變數),在提交時檢查它。如laravel中的 _token

程式碼注入:程式碼注入是利用計算機漏洞通過處理無效資料造成的。問題出在,當你不小心執行任意程式碼,通常通過檔案包含。寫得很糟糕的程式碼可以允許一個遠端檔案包含並執行。如許多PHP函式,如require可以包含URL或檔名。
防止程式碼注入 過濾使用者輸入 在php.ini中設定禁用allow_url_fopen和allow_url_include。這將禁用require/include/fopen的遠端檔案

16 面向物件的特徵有哪些方面?

主要有封裝,繼承,多型。如果是4個方面則加上:抽象。

封裝:

封裝是保證軟體部件具有優良的模組性的基礎,封裝的目標就是要實現軟體部件的高內聚,低耦合,防止程式相互依賴性而帶來的變動影響.

繼承:

在定義和實現一個類的時候,可以在一個已經存在的類的基礎之上來進行,把這個已經存在的類所定義的內容作為自己的內容,並可以加入若干新的內容,或修改原來的方法使之更適合特殊的需要,這就是繼承。繼承是子類自動共享父類資料和方法的機制,這是類之間的一種關係,提高了軟體的可重用性和可擴充套件性。

多型:

多型是指程式中定義的引用變數所指向的具體型別和通過該引用變數發出的方法呼叫在程式設計時並不確定,而是在程式執行期間才確定,即一個引用變數倒底會指向哪個類的例項物件,該引用變數發出的方法呼叫到底是哪個類中實現的方法,必須在由程式執行期間才能決定。

抽象:

抽象就是找出一些事物的相似和共性之處,然後將這些事物歸為一個類,這個類只考慮這些事物的相似和共性之處,並且會忽略與當前主題和目標無關的那些方面,將注意力集中在與當前目標有關的方面。例如,看到一隻螞蟻和大象,你能夠想象出它們的相同之處,那就是抽象。

17說說對SQL語句優化有哪些方法?(選擇幾條)

(1)Where子句中:where表之間的連線必須寫在其他Where條件之前,那些可以過濾掉最大數量記錄的條件必須寫在Where子句的末尾.HAVING最後。

(2)用EXISTS替代IN、用NOT EXISTS替代NOT IN。

(3) 避免在索引列上使用計算

(4)避免在索引列上使用IS NULL和IS NOT NULL

(5)對查詢進行優化,應儘量避免全表掃描,首先應考慮在 where 及 order by 涉及的列上建立索引。

(6)應儘量避免在 where 子句中對欄位進行 null 值判斷,否則將導致引擎放棄使用索引而進行全表掃描

(7)應儘量避免在 where 子句中對欄位進行表示式操作,這將導致引擎放棄使用索引而進行全表掃描

18 MySQL資料庫作釋出系統的儲存,一天五萬條以上的增量,預計運維三年,怎麼優化?

(1)設計良好的資料庫結構,允許部分資料冗餘,儘量避免join查詢,提高效率。

(2) 選擇合適的表字段資料型別和儲存引擎,適當的新增索引。

(3) 做mysql主從複製讀寫分離。

(4)對資料表進行分表,減少單表中的資料量提高查詢速度。

(5)新增快取機制,比如redis,memcached等。

(6)對不經常改動的頁面,生成靜態頁面(比如做ob快取)。

(7)書寫高效率的SQL。比如 SELECT * FROM TABEL 改為 SELECT field_1, field_2, field_3 FROM TABLE.

19 對於大流量的網站,您採用什麼樣的方法來解決各頁面訪問量統計問題?

(1) 確認伺服器是否能支撐當前訪問量。

(2) 優化資料庫訪問。

(3)禁止外部訪問連結(盜鏈), 比如圖片盜鏈。

(4)控制檔案下載。

(5)做負載均衡,使用不同主機分流。

(6)使用瀏覽統計軟體,瞭解訪問量,有針對性的進行優化。

20 談談你對 mysql 引擎中的 MyISAM與InnoDB的區別理解?

InnoDB和MyISAM是許多人在使用MySQL時最常用的兩個表型別,這兩個表型別各有優劣,視具體應用而定。基本的差別為:MyISAM型別不支援事務處理等高階處理,而InnoDB型別支援。MyISAM型別的表強調的是效能,其執行數度比InnoDB型別更快,但是不提供事務支援,而InnoDB提供事務支援已經外部鍵等高階資料庫功能。

以下是一些細節和具體實現的差別:

MyISAM與InnoDB的區別是什麼?

1、 儲存結構

MyISAM:每個MyISAM在磁碟上儲存成三個檔案。第一個檔案的名字以表的名字開始,副檔名指出檔案型別。.frm檔案儲存表定義。資料檔案的副檔名為.MYD (MYData)。索引檔案的副檔名是.MYI (MYIndex)。

InnoDB:所有的表都儲存在同一個資料檔案中(也可能是多個檔案,或者是獨立的表空間檔案),InnoDB表的大小隻受限於作業系統檔案的大小,一般為2GB。

2、 儲存空間

MyISAM:可被壓縮,儲存空間較小。支援三種不同的儲存格式:靜態表(預設,但是注意資料末尾不能有空格,會被去掉)、動態表、壓縮表。

InnoDB:需要更多的記憶體和儲存,它會在主記憶體中建立其專用的緩衝池用於高速緩衝資料和索引。

3、 可移植性、備份及恢復

MyISAM:資料是以檔案的形式儲存,所以在跨平臺的資料轉移中會很方便。在備份和恢復時可單獨針對某個表進行操作。

InnoDB:免費的方案可以是拷貝資料檔案、備份 binlog,或者用 mysqldump,在資料量達到幾十G的時候就相對痛苦了。

4、 事務支援

MyISAM:強調的是效能,每次查詢具有原子性,其執行數度比InnoDB型別更快,但是不提供事務支援。

InnoDB:提供事務支援事務,外部鍵等高階資料庫功能。 具有事務(commit)、回滾(rollback)和崩潰修復能力(crash recovery capabilities)的事務安全(transaction-safe (ACID compliant))型表。

5、 AUTO_INCREMENT

MyISAM:可以和其他欄位一起建立聯合索引。引擎的自動增長列必須是索引,如果是組合索引,自動增長可以不是第一列,他可以根據前面幾列進行排序後遞增。

InnoDB:InnoDB中必須包含只有該欄位的索引。引擎的自動增長列必須是索引,如果是組合索引也必須是組合索引的第一列。

6、 表鎖差異

MyISAM:只支援表級鎖,使用者在操作myisam表時,select,update,delete,insert語句都會給表自動加鎖,如果加鎖以後的表滿足insert併發的情況下,可以在表的尾部插入新的資料。

InnoDB:支援事務和行級鎖,是innodb的最大特色。行鎖大幅度提高了多使用者併發操作的新能。但是InnoDB的行鎖,只是在WHERE的主鍵是有效的,非主鍵的WHERE都會鎖全表的。

7、 全文索引

MyISAM:支援 FULLTEXT型別的全文索引

InnoDB:不支援FULLTEXT型別的全文索引,但是innodb可以使用sphinx外掛支援全文索引,並且效果更好。

8、 表主鍵

MyISAM:允許沒有任何索引和主鍵的表存在,索引都是儲存行的地址。

InnoDB:如果沒有設定主鍵或者非空唯一索引,就會自動生成一個6位元組的主鍵(使用者不可見),資料是主索引的一部分,附加索引儲存的是主索引的值。

9、 表的具體行數

MyISAM:儲存有表的總行數,如果select count(*) from table;會直接取出出該值。

InnoDB:沒有儲存表的總行數,如果使用select count(*) from table;就會遍歷整個表,消耗相當大,但是在加了wehre條件後,myisam和innodb處理的方式都一樣。

10、 CURD操作

MyISAM:如果執行大量的SELECT,MyISAM是更好的選擇。

InnoDB:如果你的資料執行大量的INSERT或UPDATE,出於效能方面的考慮,應該使用InnoDB表。DELETE 從效能上InnoDB更優,但DELETE FROM table時,InnoDB不會重新建立表,而是一行一行的刪除,在innodb上如果要清空儲存有大量資料的表,最好使用truncate table這個命令。

11、 外來鍵

MyISAM:不支援

InnoDB:支援

通過上述的分析,基本上可以考慮使用InnoDB來替代MyISAM引擎了,原因是InnoDB自身很多良好的特點,比如事務支援、儲存 過程、檢視、行級鎖定等等,在併發很多的情況下,相信InnoDB的表現肯定要比MyISAM強很多。另外,任何一種表都不是萬能的,只用恰當的針對業務型別來選擇合適的表型別,才能最大的發揮MySQL的效能優勢。如果不是很複雜的Web應用,非關鍵應用,還是可以繼續考慮MyISAM的,這個具體情況可以自己斟酌。

點關注,不迷路

好了各位,以上就是這篇文章的全部內容了,能看到這裡的人呀,都是人才。之前說過,PHP方面的技術點很多,也是因為太多了,實在是寫不過來,寫過來了大家也不會看的太多,所以我這裡把它整理成了PDF和文件,如果有需要的可以

點選進入暗號: PHP+「平臺」


更多學習內容可以訪問【對標大廠】精品PHP架構師教程目錄大全,只要你能看完保證薪資上升一個臺階(持續更新)

以上內容希望幫助到大家,很多PHPer在進階的時候總會遇到一些問題和瓶頸,業務程式碼寫多了沒有方向感,不知道該從那裡入手去提升,對此我整理了一些資料,包括但不限於:分散式架構、高可擴充套件、高效能、高併發、伺服器效能調優、TP6,laravel,YII2,Redis,Swoole、Swoft、Kafka、Mysql優化、shell指令碼、Docker、微服務、Nginx等多個知識點高階進階乾貨需要的可以免費分享給大家,需要的可以加入我的 PHP技術交流群