3 個PHP 知識總結:Memcache、快取和正則

語言: CN / TW / HK

點選進入“PHP開源社群”    

免費獲取進階面試、文件、影片資源

PHP使用Memcache來儲存session

很多時候一個完整的系統可能執行在多個伺服器上,如果這多個伺服器之間需要共享session的話,那麼PHP預設的files儲存session的方式就無能為力了。這時我們可以考慮使用Memcache來接管session的儲存與讀取工作。

方法I:  在 php.ini 中全域性設定

php.ini程式碼

session.save_handler = memcache

session.save_path = "tcp://127.0.0.1:11211"

方法II:某個目錄下的 .htaccess

php.ini程式碼

php_value session.save_handler "memcache"

php_value session.save_path "tcp://127.0.0.1:11211"

方法III:再或者在某個一個應用中

PHP程式碼

ini_set("session.save_handler", "memcache");

ini_set("session.save_path", "tcp://127.0.0.1:11211");

使用多個 memcached server 時用逗號”,”隔開,

並且和 Memcache::addServer() 文件中說明的一樣,

可以帶額外的引數”persistent”、”weight”、”timeout”、”retry_interval” 等等,

類似這樣的:”tcp://host1:port1?persistent=1&weight=2,tcp://host2:port2″ 。

如果安裝的PECL是memcached(依賴libmemcached庫的那個擴充套件),則配置應為

PHP程式碼

ini_set("session.save_handler", "memcached"); // 是memcached不是memcache

ini_set("session.save_path", "127.0.0.1:11211"); // 不要tcp

PHP 緩衝區總結

在有些迴圈執行的語句,瀏覽器沒有預期的輸出,到底是什麼問題呢?本篇文章主要講解下PHP緩衝區。對於PHP來說,每一次像 echo輸出等操作,先是寫入到了 php buffer 裡,在指令碼執行完畢或者執行了強制輸出快取操作,資料才會在瀏覽器上顯示。

我們先來看一段程式碼。

for ($i=10; $i>0; $i--){

echo $i;

flush();

sleep(1);

}

按照php手冊裡的說法,該函式將當前為止程式的所有輸出傳送到使用者的瀏覽器。上面的這段程式碼,應該隔一秒鐘輸出一次$i。但是實際中卻不一定是這樣。有可能是等了10秒鐘後,所有的輸出同時呈現出來。

好,我們來改一下這段程式碼,改成

ob_end_clean();//修改部分

for ($i=10; $i>0; $i--){

echo $i;

flush();

sleep(1);

}

嘿,加了這一句ob_end_clean();,居然就OK了。實際上,我們把ob_end_clean()換成ob_end_flush()也一樣OK。

我再來改一改。

for ($i=10; $i>0; $i--){

echo $i;

ob_flush();//修改部分

flush();

sleep(1);

}

執行一下,是不是發現$i也隔一秒輸出一次了?這是為什麼呢?

別急,我們來看看php.ini。

開啟php.ini,搜尋output_buffering,我們會看到類似這樣的設定 output_buffering = 4096。正如它的名字output_buffering一樣,這個設定的作用就是把輸出緩衝一下,緩衝大小為4096bytes.

在我們的第一段程式碼裡,之所以沒有按預期的輸出,正是因為這個output_buffering把那些輸出都緩衝了。沒達到4096bytes或者指令碼結束,輸出是不會被髮送出去的。

而第二段程式碼中的ob_end_clean()和ob_end_flush()的作用,就是終止緩衝。這樣就不用等到有4096bytes的緩衝之後才被髮送出去了。

第三段程式碼中,用了一句ob_flush(),它的作用就是把緩衝的資料傳送出去,但是並不會終止緩衝,所以它必須在每次flush()前使用。

如果不想使用ob_end_clean(),ob_end_flush()和ob_flush(),我們就必須把php.ini裡的output_buffering設得足夠小,例如設為0。需要注意的是,如果你打算在指令碼中使用ini_set(“output_buffering”,”0″)來設定,那麼請停下來吧,這種方法是不行的。因為在指令碼一開始的時候,緩衝設定就已經被載入,然後緩衝就開始了。

可能你會問了,既然ob_flush()是把緩衝的資料傳送出去,那麼為什麼還需要用flush()???直接用下面這段程式碼不行嗎??

for ($i=10; $i>0; $i--){

echo $i;

ob_flush();

sleep(1);

}

請注意ob_flush()和flush()的區別。前者是把資料從PHP的緩衝中釋放出來,後者是把不在緩衝中的或者說是被釋放出來的資料傳送到瀏覽器。所以當緩衝存在的時候,我們必須ob_flush()和flush()同時使用。

那是不是flush()在這裡就是不可缺少的呢?不是的,我們還有另外一種方法,使得當有資料輸出的時候,馬上被髮送到瀏覽器。下面這兩段程式碼就是不需要使用flush()了。(當你把output_buffering設為0的時候,連ob_flush()和ob_end_clean()都不需要了)

ob_implicit_flush(true);

for ($i=10; $i>0; $i--){

echo $i;

ob_flush(); #如果ob函式開啟的情況下

sleep(1);

}



ob_end_clean();

ob_implicit_flush(true);

for ($i=10; $i>0; $i--){

echo $i;

sleep(1);

}

請注意看上面的ob_implicit_flush(true),這個函式強制每當有輸出的時候,即刻把輸出傳送到瀏覽器。這樣就不需要每次輸出(echo)後,都用flush()來發送到瀏覽器了。

以上所訴可能在某些瀏覽器中不成立。因為瀏覽器也有自己的規則。我是用Firefox1.5,IE6,opera8.5來測試的。其中opera就不能正常輸出,因為它有一個規則,就是不遇到一個HTML標籤,就絕對不輸出,除非到指令碼結束。而FireFox和IE還算比較正常的。

最後附上一段非常有趣的程式碼,作者為PuTTY shell。在一個腳本週期裡,每次輸出,都會把前一次的輸出覆蓋掉。

以下程式碼只在firefox下可用,其他瀏覽器並不支援multipart/x-mixed-replace的Content-Type.

header('Content-type: multipart/x-mixed-replace;boundary=endofsection');

print "\n--endofsection\n";



$pmt = array("-", "\\", "|", "/" );

for( $i = 0; $i <10; $i ++ ){

sleep(1);

print "Content-type: text/plain\n\n";

print "Part $i\t".$pmt[$i % 4];

print "--endofsection\n";

ob_flush();

flush();

}

print "Content-type: text/plain\n\n";

print "The end\n";

print "--endofsection--\n";

PHP正則表示式的運用

正則表示式是PHP中一個非常重要的知識點,通常用來查詢和替換字串,驗證使用者輸入的資訊格式是否符合規範,如郵件格式、電話格式等等。

還有采集器之類的軟體中,正則也是必用不可!主要介紹PHP中幾個常見的正則函式:preg_match()、preg_match_all()、preg_grep()、preg_split()。

1. preg_match()

該函式通常用於表單驗證。可以按指定的正則表示式模式,對字串進行搜尋和匹配一次.該函式有兩個必選引數,第一個引數需要提供使用者按正則表示式語法編寫的模式,第二個引數需要一個字串。

如果提供了第三個可選的陣列引數matches,則可以擁有儲存第一個引數中的子模式的各個部分的匹配結果。

2. preg_match_all()

該函式與preg_match()函式類似,不同的是函式preg_match()在第一次匹配之後就會停止搜尋。而函式preg_match_all()則會一直搜尋到指定字串的結尾,可以獲取到所有匹配到的結果。

該函式把所有可能的匹配結果放入第三個引數的陣列中,並返回整個模式匹配的次數,如果出錯則返回False。如果使用了第四個引數,會根據它指定的順序將每次出現的匹配結果儲存到第三個引數的陣列中。第四個引數有兩個預定義的值

a.PREG_PATTERN_ORDER: 它是preg_match_all() 函式的預設值,對結果排序使$matches[0]為全部模式匹配的陣列,$matches[1] 為第一個括號中的子模式所匹配的字串組成的陣列,以此類推。

b.PREG_SET_ORDER: 對結果排序是$matches[0]為第一組匹配項的陣列,$matches[1]為第二組匹配項的陣列,以此類推。

3. preg_grep()

該函式與前兩個函式不同的是匹配陣列中的元素,返回與正則表示式匹配的陣列單元。

該函式返回一個數組,其中包括了第二個引數陣列中與給定的第一個引數模式相匹配的單元,對於輸出陣列的每個元素,進行依稀匹配。

4. preg_replace()

該函式可執行正則表示式的搜尋和替換,是一個最強大的字串替換處理函式。

該函式的三個引數,第一個引數匹配項,二個引數被替換的引數。第三個被搜多的引數。如果指定第四個可選引數limit ,則僅替換limit個匹配,如果生了limit 或者其值為-1,則所有的匹配項都會被替換。

5. str_replace()

該函式是PHP提高的字串處理函式,也可以實現字串的替換工資。雖然沒有正則表示式的替換函式功能強大,但一些簡單字串的替換要比preg_replace()函式的執行效率高。

該函式有單個必選引數,還有一個可選引數, 第一個引數是目標物件,第二個引數是替換物件,第三個是被處理的字串,該函式在第三個引數的字串中,以區分大小寫的方式搜尋第一個引數提高的目標物件,

並用第二個引數所提供的替換物件替換找到的所有例項。

如果沒有在第三個引數中搜索到目標物件,則被處理的字串保持不變。

第四個是一個可選引數,變數的引用,必須傳入一個變數名稱,用來儲存替換的次數。

使用str_replace()的前兩個引數不僅可以使用字串,也可以使陣列。

6. preg_split()

該函式使用了Perl相容的正則表示式語法,可以按正則表示式的方法分割字串。

該函式返回一個字串陣列,陣列中元素包含通過第二個引數中的字串,經第一個引數的正則表示式,作為匹配的邊界分割的子串。如果指定了第三個字串limit,則最多返回linmit個子串。而其中最後一個元素包含了被分割後剩餘的所有部分。如果limit是-1,則意味著沒有限制。

第四個引數是可選引數,

>> PREG_SPLIT_NO_EMPTY:如果設定了本標記,則preg_split()只返回非空的成分

>> PREG_SPLIT_DELIM_CAPTURE: 如果設定了本標記,定界符模式中的括號表示式也會被捕獲並返回

>> PREG_SPLIT_OFFSET_CAPTURE: 如果設定了本標記,對每個出現的匹配結果也同時返回其附屬的字串偏移量。注意這改變了返回的陣列的值,使其中的每個單元也是一個數組,其中第一項為匹配字串,第二項為其在原字串中的偏移量。

函式 explode()

如果僅用某個特定的字串進行分割,建議使用explode()函式,它不用去呼叫正則表示式引擎,因此速度是最快的。

該函式有三個引數,第一個引數提高一個分割字元或是字串,第二個引數是被分割的字串,如果提供第三個可選引數limit,則指定最多將字串分割為多少個子串。

該函式返回一個由被分割的子字串組成的陣列。

函式 implode()

與分割字串相對應的是implode()函式,把陣列中所有元素組合為一個字串。函式join()為該函式的別名。

該函式PHP 事件擴充套件 Event 釋出 3.0.0 beta 版本,正式支援 PHP 8有兩個引數,第一個引數提高一個連結字元或字串,第二個引數指定一個被連結的陣列。

*宣告:本文於網路整理,版權歸原作者所有,如來源資訊有誤或侵犯權益,請聯絡我們刪除或授權事宜。

END

PHP開源社群

掃描關注  進入”PHP資料“

免費獲取進階

面試、文件、影片資源

點選“檢視原文”獲取更多