PHP常見面試題(更新)

--------PHP常見面試題

1.什麼是面向對象?(理解着回答)
面向對象是一種思想,是基於面向過程而言的,就是說面向對象是將功能等通過對象來實現,將功能封裝進對象之中,讓對象去實現具體的細節。

面向對象有三大特徵:封裝性、繼承性、多態性。

現在純正的OO語言主要是 Java 和 C#,PHP、C++也支持OO,C是面向過程的。

2.面向對象的特徵有哪些方面?
主要有封裝,繼承,多態。如果是4個方面則加上:抽象。

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

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

多態:
多態是指程序中定義的引用變量所指向的具體類型和通過該引用變量發出的方法調用在編程時並不確定,而是在程序運行期間才確定,即一個引用變量倒底會指向哪個類的實例對象,該引用變量發出的方法調用到底是哪個類中實現的方法,必須在由程序運行期間才能決定。

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

3.抽象類和接口的概念以及區別?

抽象類:它是一種特殊的,不能被實例化的類,只能作爲其他類的父類使用。使用abstract關鍵字聲明。

接口:它是一種特殊的抽象類,也是一個特殊的類,使用interface聲明。

區別:

(1)抽象類的操作通過繼承關鍵字extends實現,而接口的使用是通過implements關鍵字來實現。

(2)抽象類中有數據成員,可以實現數據的封裝,但是接口沒有數據成員。

(3)抽象類中可以有構造方法,但是接口沒有構造方法。

(4)抽象類的方法可以通過private、protected、public關鍵字修飾(抽象方法不能是private),而接口中的方法只能使用public關鍵字修飾。

(5)一個類只能繼承於一個抽象類,而一個類可以同時實現多個接口。

(6)抽象類中可以有成員方法的實現代碼,而接口中不可以有成員方法的實現代碼。

4.什麼是構造函數,什麼是析構函數,作用是什麼?

構造函數(方法)是對象創建完成後第一個被對象自動調用的方法。它存在於每個聲明的類中,是一個特殊的成員方法。作用是執行一些初始化的任務。Php中使用__construct()聲明構造方法,並且只能聲明一個。

析構函數(方法)作用和構造方法正好相反,是對象被銷燬之前最後一個被對象自動調用的方法。是PHP5中新添加的內容作用是用於實現在銷燬一個對象之前執行一些特定的操作,諸如關閉文件和釋放內存等。

5.堆和棧的區別?
堆是程序運行期間動態分配的內存空間,你可以根據程序的運行情況確定要分配的堆內存的大小。

棧是編譯期間就分配好的內存空間,因此你的代碼中必須就棧的大小有明確的定義;

6.__autoload()方法的工作原理是什麼?

使用這個魔術函數的基本條件是類文件的文件名要和類的名字保持一致。

當程序執行到實例化某個類的時候,如果在實例化前沒有引入這個類文件,那麼就自動執行__autoload()函數。

這個函數會根據實例化的類的名稱來查找這個類文件的路徑,當判斷這個類文件路徑下確實存在這個類文件後

就執行include或者require來載入該類,然後程序繼續執行,如果這個路徑下不存在該文件時就提示錯誤。

使用自動載入的魔術函數可以不必要寫很多個include或者require函數。

7.編譯和緩存區別?

smarty的編譯過程就是把模板拿過來,把裏面的標籤替換成相應php代碼,這就是smarty的編譯, 其實就是php和html混合的過程
smarty的緩存需要手動開啓,smarty的緩存就是把編譯好的文件執行後,同時生成一份靜態的html頁面,再次訪問的時候,你訪問的就是是html文件了,所以就效率來說,要高一些。

8.什麼是smarty? Smarty的優點是什麼?
Smarty是一個使用PHP寫出來的PHP模板引擎,目的是要使用PHP程序同美工分離,使的程序員改變程序的邏輯內容時不會影響到美工的頁面設計,美工重新修改頁面時不會影響到程序的程序邏輯,這在多人合作的項目中顯的尤爲重要。(也易於程序的多樣式開發)

Smarty優點

(1)速度快:相對其他模板引擎。

(2) 編譯型:採用smarty編寫的程序在運行時要編譯成一個非模板技術的PHP文件

(3)緩存技術:它可以將用戶最終看到的HTML文件緩存成一個靜態的HTML頁

(4)插件技術:smarty可以自定義插件。

不適合使用smarty的地方

(1)需要實時更新的內容。例如像股票顯示,它需要經常對數據進行更新

(2)小項目。小項目因爲項目簡單而美工與程序員兼於一人的項目

9.在PHP中error_reporting這個函數有什麼作用?

設置PHP的報錯級別並返回當前級別。

10.說說你對緩存技術的瞭解?

緩存技術是將動態內容緩存到文件中,在一定時間內訪問動態頁面直接調用緩存文件,而不必重新訪問數據庫。

11.現在編程中經常採取MVC三層結構,請問MVC分別指哪三層,有什麼優點?

MVC三層分別指:業務模型、視圖、控制器,由控制器層調用模型處理數據,然後將數據映射到視圖層進行顯示,優點是:①可以實現代碼的重用性,避免產生代碼冗餘;②M和V的實現代碼分離,從而使同一個程序可以使用不同的表現形式

12.foo()和@foo()之間有什麼區別?
@代表所有warning忽略

13、常用的魔術方法有哪些?舉例說明
php規定以兩個下劃線(__)開頭的方法都保留爲魔術方法,建議大家函數名最好不用__開頭,除非是爲了重載已有的魔術方法。

__construct() 實例化類時自動調用。
__destruct() 類對象使用結束時自動調用。
__set() 在給未定義的屬性賦值的時候調用。
__get() 調用未定義的屬性時候調用。
__isset() 使用isset()或empty()函數時候會調用。
__unset() 使用unset()時候會調用。
__sleep() 使用serialize序列化時候調用。
__wakeup() 使用unserialize反序列化的時候調用。
__call() 調用一個不存在的方法的時候調用。
__callStatic()調用一個不存在的靜態方法是調用。
__toString() 把對象轉換成字符串的時候會調用。比如 echo。
__invoke() 當嘗試把對象當方法調用時調用。
__set_state() 當使用var_export()函數時候調用。接受一個數組參數。
__clone() 當使用clone複製一個對象時候調用。

14.支付寶流程怎麼實現的?

答:首先要有一個支付寶賬號,接下來向支付寶申請在線支付業務,簽署協議。協議生效後有支付寶一方會給網站方一個合作伙伴ID,和安全校驗碼,有了這兩樣東西就可以按照支付寶接口文檔開發支付寶接口了,中間主要涉及到一個安全問題。整個流程是這樣的:我們的網站通過post傳遞相應的參數(如訂單總金額,訂單號)到支付頁面,支付頁面把一系列的參數經過處理,以post的方式提交給支付寶服務器,支付寶服務器進行驗證,並對接收的數據進行處理,把處理後的結果返回給我們網站設置的異步和同步回調地址,通過相應的返回參數,來處理相應的業務邏輯,比如返回的參數代表支付成功,更改訂單狀態。

14.做秒殺時鎖表考慮到沒有?

答:考慮到了,當時我們做秒殺時考慮了好幾種方案,其中有一種就是使用事務加上排他鎖來實現。

15.如何處理負載、高併發?(好好看看,經常問到,能回答到主要的東西即可)?
答:從低成本、高性能和高擴張性的角度來說有如下處理方案:

1、HTML靜態化

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

2、圖片服務器分離

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

3、數據庫集羣和庫表散列及緩存

數據庫的併發連接爲100,一臺數據庫遠遠不夠,可以從讀寫分離、主從複製,數據庫集羣方面來着手。另外儘量減少數據庫的訪問,可以使用緩存數據庫如memcache、redis。

4、鏡像:

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

5、負載均衡:

Apache的最大併發連接爲1500,只能增加服務器,可以從硬件上着手,如F5服務器。當然硬件的成本比較高,我們往往從軟件方面着手。

負載均衡 (Load Balancing) 建立在現有網絡結構之上,它提供了一種廉價有效透明的方法擴展網絡設備和服務器的帶寬、增加吞吐量、加強網絡數據處理能力,同時能夠提高網絡的靈活性和可用性。目前使用最爲廣泛的負載均衡軟件是Nginx、LVS、HAProxy。我分別來說下三種的優缺點:

Nginx的優點是:

工作在網絡的7層之上,可以針對http應用做一些分流的策略,比如針對域名、目錄結構,它的正則規則比HAProxy更爲強大和靈活,這也是它目前廣泛流行的主要原因之一,Nginx單憑這點可利用的場合就遠多於LVS了。

Nginx對網絡穩定性的依賴非常小,理論上能ping通就就能進行負載功能,這個也是它的優勢之一;相反LVS對網絡穩定性依賴比較大,這點本人深有體會;

Nginx安裝和配置比較簡單,測試起來比較方便,它基本能把錯誤用日誌打印出來。LVS的配置、測試就要花比較長的時間了,LVS對網絡依賴比較大。

可以承擔高負載壓力且穩定,在硬件不差的情況下一般能支撐幾萬次的併發量,負載度比LVS相對小些。

Nginx可以通過端口檢測到服務器內部的故障,比如根據服務器處理網頁返回的狀態碼、超時等等,並且會把返回錯誤的請求重新提交到另一個節點,不過其中缺點就是不支持url來檢測。比如用戶正在上傳一個文件,而處理該上傳的節點剛好在上傳過程中出現故障,Nginx會把上傳切到另一臺服務器重新處理,而LVS就直接斷掉了,如果是上傳一個很大的文件或者很重要的文件的話,用戶可能會因此而不滿。

Nginx不僅僅是一款優秀的負載均衡器/反向代理軟件,它同時也是功能強大的Web應用服務器。LNMP也是近幾年非常流行的web架構,在高流量的環境中穩定性也很好。

Nginx現在作爲Web反向加速緩存越來越成熟了,速度比傳統的Squid服務器更快,可以考慮用其作爲反向代理加速器。

Nginx可作爲中層反向代理使用,這一層面Nginx基本上無對手,唯一可以對比Nginx的就只有 lighttpd了,不過 lighttpd目前還沒有做到Nginx完全的功能,配置也不那麼清晰易讀,社區資料也遠遠沒Nginx活躍。

Nginx也可作爲靜態網頁和圖片服務器,這方面的性能也無對手。還有Nginx社區非常活躍,第三方模塊也很多。

Nginx的缺點是:

Nginx僅能支持http、https和Email協議,這樣就在適用範圍上面小些,這個是它的缺點。

對後端服務器的健康檢查,只支持通過端口來檢測,不支持通過url來檢測。不支持Session的直接保持,但能通過ip_hash來解決。

LVS:使用Linux內核集羣實現一個高性能、高可用的負載均衡服務器,它具有很好的可伸縮性(Scalability)、可靠性(Reliability)和可管理性(Manageability)。

16、對於大流量的網站,您採用什麼樣的方法來解決各頁面訪問量統計問題。
A、確認服務器是否能支撐當前訪問量;
B、優化數據庫訪問;
C、禁止外部訪問鏈接(盜鏈), 比如圖片防盜鏈;
D、控制文件下載,尤其是大文件;
E、使用不同主機分流(負載均衡);
F、使用瀏覽統計軟件,瞭解訪問量,有針對性的進行優化。

17、Mysql的存儲引擎,myisam和innodb的區別。

A、MyISAM類型不支持事務處理等高級處理,而InnoDB類型支持;
B、MyISAM類型的表強調的是性能,其執行速度比InnoDB類型更快;
C、InnoDB不支持FULLTEXT類型的索引;
D、InnoDB中不保存表的具體行數,也就是說,執行select count(*) from table時,InnoDB要掃描一遍整個表來計算有多少行,但是MyISAM只要簡單的讀出保存好的行數即可;
E、對於AUTO_INCREMENT類型的字段,InnoDB中必須包含只有該字段的索引,但是在MyISAM表中,可以和其他字段一起建立聯合索引;
F、DELETE FROM table時,InnoDB不會重新建立表,而是一行一行的刪除;
G、LOAD TABLE FROM MASTER操作對InnoDB是不起作用的,解決方法是首先把InnoDB表改成MyISAM表,導入數據後再改成InnoDB表,但是對於使用的額外的InnoDB特性(例如外鍵)的表不適用;
H、MyISAM支持表鎖,InnoDB支持行鎖。

MyISAM:成熟、穩定、易於管理,快速讀取。一些功能不支持(事務等),表級鎖。
InnoDB:支持事務、外鍵等特性、數據行鎖定。空間佔用大,不支持全文索引等。

18、HTTP 狀態中302、403、 500代碼含義?
一二三四五原則:(即一:消息系列;二:成功系列; 三:重定向系列;四:請求錯誤系列;五:服務器端錯誤系列。)
302:臨時轉移成功,請求的內容已轉移到新位置
403:禁止訪問
500:服務器內部錯誤
401:代表未授權。

19、請寫出數據類型(int char varchar datetime text)的意思;請問 varchar 和 char有什麼區別?

Int 整數char 定長字符 Varchar 變長字符 Datetime 日期時間型Text 文本型 Varchar與char的區別 char是固定長度的字符類型,分配多少空間,就佔用多長空間。Varchar是可變長度的字符類型,內容有多大就佔用多大的空間,能有效節省空間。由於varchar類型是可變的,所以在數據長度改變的時,服務器要進行額外的操作,所以效率比char類型低。

20、MyISAM和 InnoDB 的基本區別?索引結構如何實現?
A、MyISAM類型不支持事務,表鎖,易產生碎片,要經常優化,讀寫速度較快,適合用於頻繁查詢的應用;
B、InnoDB類型支持事務,行鎖,有崩潰恢復能力,讀寫速度比MyISAM慢,適合於插入和更新操作比較多的應用,空間佔用大,不支持全文索引等。
創建索引:alert table tablename add index 索引名 (字段名)

21、請說明 PHP 中傳值與傳引用的區別。什麼時候傳值什麼時候傳引用?

按值傳遞:函數範圍內對值的任何改變在函數外部都會被忽略
按引用傳遞:函數範圍內對值的任何改變在函數外部也能反映出這些修改
優缺點:按值傳遞時,php必須複製值。特別是對於大型的字符串和對象來說,這將會是一個代價很大的操作。按引用傳遞則不需要複製值,對於性能提高很有好處。

22、SESSION 與 COOKIE的區別是什麼,請從協議,產生的原因與作用說明?
A、http無狀態協議,不能區分用戶是否是從同一個網站上來的,同一個用戶請求不同的頁面不能看做是同一個用戶。
B、SESSION存儲在服務器端,COOKIE保存在客戶端。Session比較安全,cookie用某些手段可以修改,不安全。Session依賴於cookie進行傳遞。
禁用cookie後,session不能正常使用。Session的缺點:保存在服務器端,每次讀取都從服務器進行讀取,對服務器有資源消耗。Session保存在服務器端的文件或數據庫中,默認保存在文件中,文件路徑由php配置文件的session.save_path指定。Session文件是公有的。

23.PHP中獲取圖像尺寸大小的方法是什麼?
回答:getimagesize () 獲取圖片的尺寸
Imagesx () 獲取圖片的寬度
Imagesy () 獲取圖片的高度

24、AJAX的優勢是什麼?

ajax是異步傳輸技術,可以通過java實現,也可以通過JQuery框架實現,實現局部刷新,減輕了服務器的壓力,也提高了用戶體驗。

25.悲觀鎖和樂觀鎖?
樂觀鎖只適合只有讀沒有寫的操作,
悲觀鎖適合讀寫操作,但是讀寫操作可增加CPU的緩存失效率。

26、語句include和require的區別是什麼?爲避免多次包含同一文件,可用什麼語句代替它們?

區別:
在失敗的時候:
include產生一個warning,而require產生直接產生錯誤中斷
require在運行前載入
include在運行時載入
代替:
require_once
include_once

27、安全對一套程序來說至關重要,請說說在開發中應該注意哪些安全機制?

①防遠程提交;②防SQL注入,對特殊代碼進行過濾;③防止註冊機灌水,使用驗證碼;

28.Composer有幾種自動加載方式,分別是哪些?
目前爲止,Composer一共支持4種自動加載方式

1.直接包含file

2.PSR-0

3.PSR-4

4.class-map

PSR-4

PSR-4是Composer推薦使用的一種方式,因爲它更易使用並能帶來更簡潔的目錄結構。在一個擴展的composer.json裏是這樣進行配置的:

{

    "autoload": {

        "psr-4": {

            "Foo\\": "src/",

        }

    }

}

key和value就定義出了namespace以及其對應的目錄映射。按照PSR-4的規則,當試圖自動加載"Foo\Bar\Baz"類的使用,會去尋找"srcBarBaz.php"這個文件,如果它存在則加載,要注意的是此時"Foo"並不會出現在文件路徑中。

而composer.json這樣的配置會被Composer轉換成namespace與文件目錄的MAP形式,並存在vendor/composer/autoload_psr4.php文件中,所以如果你安裝的某個擴展自動加載是PSR-4形式,你可以在autoload_psr4.php找到它的真實路徑。

PSR-0

這是一個已經過時的標準,那是在遙遠的PHP5.2時代,你我都知道,PHP5.3之後纔有了類似namespace這樣的高級屬性,所以PSR-0更多是考慮<=5.2時代的擴展,於是乎PSR組織用了一個僞namespace的做法。

有點蒙圈麼?那我們來看代碼你就明白了。

{

    "autoload": {

        "psr-0": {

            "Foo\\": "src/",

        }

    }

}

我們來分析這個擴展的加載方式,什麼是僞namespace那?當我們用這個庫的時候

$model= newFoo_Bar_Baz();

對的,PSR-0的時代,有很多以下劃線分隔的類名,它代表。。。它代表。。。

src/Foo/Bar/Baz.php

聰明的你一定明白什麼是僞namespace了吧,通過命名的下劃線來映射目錄結構。

哎,那個時代的標準制定者們也真心不容易呀。

Class-map方式

{

    "autoload": {

        "classmap": ["src/", "lib/"]

    }

  }

這個加載方式比較容易理解,當Composer開始安裝擴展的時候,會根據composer.json裏的這個 autoload 告訴的方式classmap,來遍歷src、lib目錄然後將裏面的類文件和其路徑一一對應,存放到vendor/composer/autoload_classmap.php內。

例如src/下有一個BaseController類,那麼在autoload_classmap.php文件中,就會生成這樣的配置:

1’BaseController’=> $baseDir. ‘/src/BaseController.php’

若你還不懂,去看看autoload_classmap.php吧。

File方式

有了上面這些加載方式還不夠麼? 是的,還會有一些供全局使用的比如幫助等這樣函數,那麼好吧,我們就講這些文件直接包含進來好了。

{

    "autoload": {

        "files": ["src/MyLibrary/functions.php"]

    }

}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章