1. 程式人生 > >【面試那些事兒二】 PHP 常見問題

【面試那些事兒二】 PHP 常見問題

PHP 的垃圾回收機制:

PHP垃圾回收機制是php5之後才有的這<span id="transmark"></span>個東西,下面我來給大家介紹一下關於PHP垃圾回收機制一些理解,希望對各位同學有所幫助。  
  
php 5.3之前使用的垃圾回收機制是單純的“引用計數”,也就是每個記憶體物件都分配一個計數器,當記憶體物件被變數引用時,計數器 1;當變數引用撤掉後,計數器-1;當計數器=0時,表明記憶體物件沒有被使用,該記憶體物件則進行銷燬,垃圾回收完成。  
  
“引用計數”存在問題,就是當兩個或多個物件互相引用形成環狀後,記憶體物件的計數器則不會消減為0;這時候,這一組記憶體物件已經沒用了,但是不能回收,從而導致記憶體洩露;  
  
php5.3開始,使用了新的垃圾回收機制,在引用計數基礎上,實現了一種複雜的演算法,來檢測記憶體物件中引用環的存在,以避免記憶體洩露  

將外網圖片本地化、將外網圖片下載到本地的原理

//將外網圖片本地化、將外網圖片下載到本地的原理  
copy("http://image.v1.cn/vodone/20150723/303862_0x0.jpg",'e:/wamp/www/303862_0x0.jpg');  

PHP快取技術總結

/** 
 
1、全頁面靜態化快取 
也就是將頁面全部生成html靜態頁面,使用者訪問時直接訪問的靜態頁面,而不會去走php伺服器解析的流程。此種方式,在CMS系 
統中比較常見,比如dedecms; 
一種比較常用的實現方式是用輸出快取: 
Ob_start() 
******要執行的程式碼******* 
$content = Ob_get_contents(); 
****將快取內容寫入html檔案***** 
Ob_end_clean(); 
 
 
2、頁面部分快取 
該種方式,是將一個頁面中不經常變的部分進行靜態快取,而經常變化的塊不快取,最後組裝在一起顯示;可以使用類似於 
ob_get_contents的方式實現,也可以利用類似ESI之類的頁面片段快取策略,使其用來做動態頁面中相對靜態的片段部分的快取 
(ESI技術,請baidu,此處不詳講)。該種方式可以用於如商城中的商品頁; 
 
 
3、資料快取 
顧名思義,就是快取資料的一種方式;比如,商城中的某個商品資訊,當用商品id去請求時,就會得出包括店鋪資訊、商品資訊 
等資料,此時就可以將這些資料快取到一個php檔案中,檔名包含商品id來建一個唯一標示;下一次有人想檢視這個商品時,首 
先就直接調這個檔案裡面的資訊,而不用再去資料庫查詢;其實快取檔案中快取的就是一個php陣列之類; 
Ecmall商城系統裡面就用了這種方式; 
 
 
4、查詢快取 
其實這跟資料快取是一個思路,就是根據查詢語句來快取;將查詢得到的資料快取在一個檔案中,下次遇到相同的查詢時,就直 
接先從這個檔案裡面調資料,不會再去查資料庫;但此處的快取檔名可能就需要以查詢語句為基點來建立唯一標示(用md5($sql)???); 
按時間變更進行快取 
其實,這一條不是真正的快取方式;上面的2、3、4的快取技術一般都用到了時間變更判斷;就是對於快取檔案您需要設一個有效 
時間,在這個有效時間內,相同的訪問才會先取快取檔案的內容,但是超過設定的快取時間,就需要重新從資料庫中獲取資料, 
並生產最新的快取檔案; 
比如,我將我們商城的首頁就是設定2個小時更新一次; 
 
 
5、按內容變更進行快取 
這個也並非獨立的快取技術,需結合著用;就是當資料庫內容被修改時,即刻更新快取檔案; 
比如,一個人流量很大的商城,商品很多,商品表必然比較大,這表的壓力也比較重;我們就可以對商品顯示頁進行頁面快取; 
當商家在後臺修改這個商品的資訊時,點選儲存,我們同時就更新快取檔案;那麼,買家訪問這個商品資訊時,實際上訪問的是 
一個靜態頁面,而不需要再去訪問資料庫; 
是想,如果對商品頁不快取,那麼每次訪問一個商品就要去資料庫查一次,如果有10萬人線上瀏覽商品,那伺服器壓力就大了; 
 
 
6、記憶體式快取 
提到這個,可能大家想到的首先就是Memcached;memcached是高效能的分散式記憶體快取伺服器。 一般的使用目的是,通過快取數 
據庫查詢結果,減少資料庫訪問次數,以提高動態Web應用的速度、 提高可擴充套件性。 
它就是將需要快取的資訊,快取到系統記憶體中,需要獲取資訊時,直接到記憶體中取;比較常用的方式就是 key-->value方式; 
     $memcachehost = '192.168.6.191'; 
     $memcacheport = 11211; 
     $memcachelife = 60; 
     $memcache = new Memcache; 
     $memcache->connect($memcachehost,$memcacheport) or die ("Could not connect"); 
     $memcache->set('key','快取的內容'); 
     $get = $memcache->get($key);       //獲取資訊 
 
 
7、apache快取模組 
apache安裝完以後,是不允許被cache的。如果外接了cache或squid伺服器要求進行web加速的話,就需要在htttpd.conf裡進行設 
置,當然前提是在安裝apache的時候要啟用mod_cache的模組。 
安裝apache時:./configure --enable-cache --enable-disk-cache --enable-mem-cache 
 
 
8、php APC快取擴充套件 
Php有一個APC快取擴充套件,windows下面為php_apc.dll,需要先載入這個模組,然後是在php.ini裡面進行配置: 
[apc]  
     extension=php_apc.dll  
     apc.rfc1867 = on  
     upload_max_filesize = 100M  
     post_max_size = 100M  
     apc.max_file_size = 200M  
     upload_max_filesize = 1000M  
     post_max_size = 1000M  
     max_execution_time = 600 ;   每個PHP頁面執行的最大時間值(秒),預設30秒  
     max_input_time = 600 ;       每個PHP頁面接收資料所需的最大時間,預設60  
     memory_limit = 128M ;       每個PHP頁面所吃掉的最大記憶體,預設8M 
 
 
9、Opcode快取 
我們知道,php的執行流程可以用下圖來展示: 
php的執行流程 
首先php程式碼被解析為Tokens,然後再編譯為Opcode碼,最後執行Opcode碼,返回結果;所以,對於相同的php檔案,第一次執行 
時可以快取其Opcode碼,下次再執行這個頁面時,直接會去找到快取下的opcode碼,直接執行最後一步,而不再需要中間的步驟了。 
比較知名的是XCache、Turck MM Cache、PHP Accelerator等; 
 
**/

遍歷函式:scandir()與glob()函式的區別

/** 
 *  scandir()與glob()函式的區別: 
 * 
 *  遍歷資料夾、遍歷目錄、遍歷子資料夾、遍歷子目錄、遍歷檔案 
 *  掃描單層資料夾的情況 
        1、scandir('E:/wamp/www/phpcms/'); 
 
            案例: 
 
            Array( 
                [0] => . 
                [1] => .. 
                [2] => admin.php 
                [3] => api 
                [4] => api.php 
                [5] => caches 
                [6] => crossdomain.xml 
                [7] => favicon.ico 
                [8] => html 
                [9] => index.html 
                [10] => index.php 
                [11] => js.html 
                [12] => nbproject 
                [13] => phpcms 
                [14] => phpsso_server 
                [15] => plugin.php 
                [16] => robots.txt 
                [17] => statics 
                [18] => uploadfile 
            ) 
 
        2、glob('E:/wamp/www/phpcms/*'); 
 
            案例: 
 
            Array( 
                [0] => E:/wamp/www/phpcms/admin.php 
                [1] => E:/wamp/www/phpcms/api 
                [2] => E:/wamp/www/phpcms/api.php 
                [3] => E:/wamp/www/phpcms/caches 
                [4] => E:/wamp/www/phpcms/crossdomain.xml 
                [5] => E:/wamp/www/phpcms/favicon.ico 
                [6] => E:/wamp/www/phpcms/html 
                [7] => E:/wamp/www/phpcms/index.html 
                [8] => E:/wamp/www/phpcms/index.php 
                [9] => E:/wamp/www/phpcms/js.html 
                [10] => E:/wamp/www/phpcms/nbproject 
                [11] => E:/wamp/www/phpcms/phpcms 
                [12] => E:/wamp/www/phpcms/phpsso_server 
                [13] => E:/wamp/www/phpcms/plugin.php 
                [14] => E:/wamp/www/phpcms/robots.txt 
                [15] => E:/wamp/www/phpcms/statics 
                [16] => E:/wamp/www/phpcms/uploadfile 
            ) 
 */  
echo "<pre>";print_r(scandir('E:/wamp/www/phpcms/'));//跟glob相比多出來兩個元素,分別是: "." 和 ".."  
echo "<pre>";print_r(glob('E:/wamp/www/phpcms/*'));//以陣列的形式返回與指定模式相匹配的檔名或目錄  

如何在陣列頭部和尾部及任意位置插入元素?

①插入元素  
array_unshift();//在陣列頭部插入一個或多個元素    
array_push();//在陣列尾部插入一個或多個元素   
array_splice($arr,$start,0,$arr1);//在陣列的第$start+1個位置插入新元素(指的是頭部和中部任意位置,但不包括尾部),注意:引數3一定要是0  
②刪除元素  
array_shift();//刪除陣列中首個元素,並返回刪除後的值  
array_pop();//刪除陣列的最後一個元素(出棧),並返回刪除後的值  

php如何方式SQL注入?我們在查詢資料庫時,出於安全考慮,需要過濾一些非法字元防止SQL惡意注入

//我們在查詢資料庫時,出於安全考慮,需要過濾一些非法字元防止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');//提示:"非法字元!!"  

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');
php如何獲取客戶端真實IP?
//我們經常要用資料庫記錄使用者的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