Archive

Posts Tagged ‘PHP’

IIS6+PHP5 (FastCGI) 安裝攻略

九月 30th, 2008

以往 PHP 的執行模式可分成 CGI 及 ISAPI 兩種,CGI 的 performance 是出名的慢,而 ISAPI 是較多人使用的,但是在 Windows 卻穩定性不佳,經常會導致整個 web server crash,所以微軟特別針對 IIS 開發了 FastCGI 模組(IIS7 已內建),據說效能及穩定性都有大大改善。

安裝步驟:
1. 確認 IIS 已經裝好,然後下載 FastCGI Extension for IIS 6 並且安裝完成。

2. 到 PHP 官網下載新版 PHP5 壓縮檔,並且解壓縮(假設在 C:\PHP5)。

3. 將 C:\PHP5\php.ini-dist 改名為 php.ini,然後依需求編輯設定檔內容,範例:
(後三行必要)

include_path = ".;C:\Inetpub\wwwroot"
extension_dir = "C:\PHP5\ext"

extension=php_curl.dll
extension=php_gd2.dll
extension=php_mbstring.dll
extension=php_mcrypt.dll
extension=php_mysql.dll
extension=php_mysqli.dll
extension=php_openssl.dll
extension=php_zip.dll

date.timezone = "Asia/Taipei"

cgi.force_redirect = 0
cgi.fix_pathinfo=1
fastcgi.impersonate = 1;

4. 對 C:\PHP5 目錄增加 IIS_WPG 群組的讀取及執行權限。
(沒加這個就會跑出 FastCGI Error)

5. 加入系統環境變數 (讓 extension 及 php.ini 能順利被找到)。
Path=C:\PHP5;
PHPRC=C:\PHP5

6. 開啟 IIS 管理員,如下圖設定。

7. 增加預設首頁 index.php

8. 檢查網頁服務延伸。
(正常的話應該會有這一項,若沒有請自行加入 C:\WINDOWS\system32\inetsrv\fcgiext.dll)

9. 開始 > 執行 > cmd
輸入四道指令(注意路徑):
cd C:\WINDOWS\system32\inetsrv

cscript fcgiconfig.js -add -section:"PHP" -extension:php -path:"C:\PHP5\php-cgi.exe"

cscript fcgiconfig.js -set -section:"PHP" -InstanceMaxRequests:10000

cscript fcgiconfig.js -set -section:"PHP" -EnvironmentVars:PHP_FCGI_MAX_REQUESTS:10000
(視情況修改數值,InstanceMaxRequests 需小於等於 PHP_FCGI_MAX_REQUESTS)

10. 重新啟動 IIS 就 OK 囉,丟一個測試檔案到網站目錄看看吧!

※2009/03/19 補充:
使用 FastCGI 執行 PHP 程式時,系統是以「NETWORK SERVICE」這個身份執行的,而一般靜態檔案則是以 IIS 預設的匿名身份「IUSR_MachineName」執行,所以如果安裝上發生問題,請特別注意這個權限配置。

相關文章:

PHP, Server, Windows, 系統筆記 , , ,

IIS6+PHP5 (ISAPI) 安裝攻略

九月 30th, 2008

最近因為特別需求要在 IIS6 上面跑 PHP,把以前寫的筆記拿出來看,卻發現怎麼弄也跑不起來,看了很多篇文章還是不行,研究了許久終於可以跑了,經過多次測試保證 100% 可行。
※ 此篇是以 ISAPI 模式執行 PHP,建議使用另一篇的 FastCGI 會有較好的效能。

安裝步驟:
1. 確認 IIS 已經裝好,到 PHP 官網下載新版 PHP5 壓縮檔,並且解壓縮(假設在 C:\PHP5)。

2. 將 C:\PHP5\php.ini-dist 改名為 php.ini,然後依需求編輯設定檔內容,範例:

include_path = ".;C:\Inetpub\wwwroot"
extension_dir = "C:\PHP5\ext"

extension=php_curl.dll
extension=php_gd2.dll
extension=php_mbstring.dll
extension=php_mcrypt.dll
extension=php_mysql.dll
extension=php_mysqli.dll
extension=php_openssl.dll
extension=php_zip.dll

date.timezone = "Asia/Taipei"

3. 對 C:\PHP5 目錄增加 IIS_WPG 群組及 IUSR_XXXX 使用者的讀取及執行權限。
(關鍵步驟,一定要兩個都增加,否則執行 PHP 會跳出驗證框)

4. 加入系統環境變數 (讓 extension 及 php.ini 能順利被找到)。
Path=C:\PHP5;
PHPRC=C:\PHP5

5. 開啟 IIS 管理員,如下圖設定。

6. 增加預設首頁 index.php

7. 增加網頁服務延伸。

8. 重新啟動 IIS 就 OK 囉,丟一個測試檔案到網站目錄看看吧!

PHP, Server, 程式筆記, 系統筆記 , , , ,

用 PHP 讀寫 Excel 檔案

九月 18th, 2008

PHP 讀寫 Excel 的方法有很多種,例如先轉成 CSV 格式來讀,然後用特定符號去分隔欄位。但是如果遇到欄位格式不固定的 Excel 就很麻煩了,所以需要可以直接操作 excel 的方法,方便直接指定要取某欄某列的值。

如果是 Windows 系統的話可以使用 COM 元件去讀取,但缺點就是只能在 Windows 上跑,失去了跨平台性,所以也有人另外寫出可以讀寫 Excel 的類別,這次要推薦的是 PHPExcelPHPExcel 的功能非常強大,原本就支援 Excel 2007,新版中也能讀取 Excel 2003 舊版的 Excel 囉!

PHPExcel 下載回來的檔案中就包含不少範例,但是讀取的部份很簡略,所以底下貼個讀取 Excel 內容的範例:


<?php
set_include_path(get_include_path() . PATH_SEPARATOR . './Classes/');
include 'PHPExcel/IOFactory.php';

$reader = PHPExcel_IOFactory::createReader('Excel5'); // 讀取舊版 excel 檔案
$PHPExcel = $reader->load("course_table.xls"); // 檔案名稱
$sheet = $PHPExcel->getSheet(0); // 讀取第一個工作表(編號從 0 開始)
$highestRow = $sheet->getHighestRow(); // 取得總列數

// 一次讀取一列
for ($row = 2; $row <= $highestRow; $row++) {

    for ($column = 1; $column <= 9; $column++) {
		$val = $sheet->getCellByColumnAndRow($column, $row)->getValue();
        echo $val . ' ';
	}
	echo "<br />";

}

PHP, 程式筆記 , ,

撰寫 PHP 程式的一些優化建議

二月 11th, 2008

這裡有一篇 Tsung 翻譯的「PHP 程式效能優化的 40 條建議」,覺得很不錯。個人接觸 PHP 這個語言約有四個年頭了,再撰寫時多少會注意一些效能細節,不過有時為了讓程式碼更好看、簡短,往往就忽略掉這些細節,這篇的建議正好可以讓新手學習、老手複習一些 PHP 的最佳化技巧。

引用內容:

  1. 如果一個方法可靜態化,就對它做靜態聲明。速率可提升至4倍
  2. echo 比 print 快
  3. 使用echo的多重參數(譯註:指用逗號而不是句點)代替字元串連接
  4. 在執行for循環之前確定最大循環數,不要每循環一次都計算最大值
  5. 註銷那些不用的變量尤其是大數組,以便釋放內存
  6. 盡量避免使用__get,__set,__autoload
  7. require_once()代價昂貴
  8. 在包含文件時使用完整路徑,解析操作系統路徑所需的時間會更少
  9. 如果你想知道腳本開始執行(譯註:即服務器端收到客戶端請求)的時刻,使用$_SERVER['REQUEST_TIME']要好於time()
  10. 函數代替正則表達式完成相同功能
  11. str_replace函數比preg_replace函數快,但strtr函數的效率是str_replace函數的四倍
  12. 如果一個字元串替換函數,可接受數組或字元作為參數,並且參數長度不太長,那麼可以考慮額外寫一段替換程式,使得每次傳遞參數是一個字元,而不是只寫一行程式接受數組作為查詢和替換的參數
  13. 使用選擇分支語句(譯註:即switch case)好於使用多個if,else if語句
  14. 用@屏蔽錯誤消息的做法非常慢
  15. 打開apache的mod_deflate模塊
  16. 資料庫連接當使用完畢時應關掉
  17. $row['id']的效率是$row[id]的7倍
  18. 錯誤訊息代價昂貴
  19. 盡量不要在for循環中使用函數,比如for ($x=0; $x < count($array); $x)每循環一次都會調用count()函數
  20. 在function中遞增局部變量,速度是最快的。幾乎與在函數中調用局部變量的速度相當
  21. 遞增一個全局變量要比遞增一個局部變量慢2倍
  22. 遞增一個物件屬性(如:$this->prop++)要比遞增一個局部變量慢3倍
  23. 遞增一個未預定義的局部變量要比遞增一個預定義的局部變量慢9至10倍
  24. 僅定義一個局部變量而沒在函數中調用它,同樣會減慢速度(其程度相當於遞增一個局部變量)。PHP大概會檢查看是否存在全局變量
  25. 方法調用看來與類中定義的方法的數量無關,因為我(在測試方法之前和之後都)添加了10個方法,但性能上沒有變化
  26. 派生類中的方法運行起來要快於在基類中定義的同樣的方法
  27. 調用帶有一個參數的空函數,其花費的時間相當於執行7至8次的局部變量遞增操作。類似的方法調用所花費的時間接近於15次的局部變量遞增操作
  28. 用單引號代替雙引號來包含字元串,這樣做會更快一些。因為PHP會在雙引號包圍的字元串中搜尋變量,單引號則不會。當然,只有當你不需要在字元串中包含變量時才可以這麼做
  29. 輸出多個字元串時,用逗號代替句點來分隔字元串,速度更快。註意:只有echo能這麼做,它是一種可以把多個字元串當作參數的“函數”(譯註:PHP手冊中說echo是語言結構,不是真正的函數,故把函數加上了雙引號)
  30. Apache解析一個PHP腳本的時間要比解析一個靜態HTML頁面慢2至10倍。盡量多用靜態HTML頁面,少用腳本
  31. 除非腳本可以緩存,否則每次調用時都會重新編譯一次。引入一套PHP緩存機制通常可以提升25%至100%的性能,以免除編譯開銷
  32. 盡量做緩存,可使用memcached。memcached是一款高性能的內存物件緩存系統,可用來加速動態Web應用程式,減輕數據庫負載。對運算碼 (OP code)的緩存很有用,使得腳本不必為每個請求做重新編譯
  33. 當操作字元串並需要檢驗其長度是否滿足某種要求時,你想當然地會使用strlen()函數。此函數執行起來相當快,因為它不做任何計算,只返回在zval 結構(C的內置數據結構,用於存儲PHP變量)中存儲的已知字元串長度。但是,由於strlen()是函數,多多少少會有些慢,因為函數調用會經過諸多步驟,如字母小寫化(譯註:指函數名小寫化,PHP不區分函數名大小寫),會跟隨被調用的函數一起執行。在某些情況下,你可以使用isset() 技巧加速執行你的程式
    舉例如下:
    if (strlen($foo) < 5) { echo "Foo is too short"; }
    與下面的技巧做比較:
    if (!isset($foo{5})) { echo "Foo is too short"; }
    調用isset()恰巧比strlen()快,因為與後者不同的是,isset()作為一種語言結構,意味著它的執行不需要函數查找和字母小寫化。也就是說,實際上在檢驗字元串長度的頂層程式中你沒有花太多開銷
  34. 當執行變數$i的遞增或遞減時,$i++會比++$i慢一些。這種差異是PHP特有的,並不適用於其他語言,所以請不要修改你的C或Java程式並指望它們能立即變快,沒用的。++$i更快是因為它只需要3條指令(opcodes),$i++則需要4條指令。後置遞增實際上會產生一個臨時變量,這個臨時變量隨後被遞增。而前置遞增直接在原值上遞增。這是最優化處理的一種,正如Zend的PHP優化器所作的那樣。牢記這個優化處理不失為一個好主意,因為並不是所有的指令優化器都會做同樣的優化處理,並且存在大量沒有裝配指令優化器的網際網路服務提供商(ISPs)和服務器
  35. 並不是所有都要使用OOP,面向物件往往開銷很大,每個方法和物件調用都會消耗很多Memory
  36. 並非要用 class 實現所有的數據結構,數組也很有用
  37. 不要把方法細分得過多,仔細想想你真正打算重用的是哪些程式?
  38. 當你需要時,你總能把程式分解成方法
  39. 盡量採用大量的PHP內置函數
  40. 如果在程式中存在大量耗時的函數,你可以考慮用C擴展的方式實現它們
  41. 評估檢驗(profile)你的程式。檢驗器會告訴你,程式的哪些部分消耗了多少時間。Xdebug調試器包含了檢驗程式,評估檢驗總體上可以顯示出程式的瓶頸
  42. mod_zip可作為Apache模塊,用來即時壓縮你的數據,並可讓數據傳輸量降低80%
  43. 另一篇優化PHP的精彩文章,由John Lim撰寫

PHP, 程式筆記 , ,

CodeIgniter 設定 MySQL 編碼

十二月 22nd, 2007

※ CodeIgniter 1.6 已釋出,不需再做這篇的修正了哦!

先前有提到CodeIgniter 這個 PHP Framework,也用它做了幾個 case,當然開發速度不能說快上多少,但確實讓程式碼變得整齊優雅許多。

使用 CI 目前遇到第一個問題是存取 MySQL 資料的問題,在 MySQL 4.1 以後採用了多層式編碼設定,簡單說就是不管是資料庫、資料表、欄位或是 Client 連線階段,都可以分別設定編碼,所以即使 server 都改成了 utf8,PHP 到 MySQL Server 的這個 connection 卻還是預設的(latin1),許多亂碼就是這樣造成的,應該已經有不少人知道解決方法,就是先送出一個改變編碼的查詢:SET NAMES 'charset'。
然而目前 CodeIgniter 並沒有這樣的設計,所以只好自行改 code 囉!

Step1:修改 system/application/config/database.php
增加一項:$db['default']['charset'] = "utf8";

Step2:修改 system/database/DB_driver.php
在 32 行之後的宣告增加:var $charset = '';
接著 96 行的陣列增加:'charset' => '',

Step3:修改 system/database/drivers/mysql/mysql_driver.php
74 行 return 前加入:


if (!empty($this->charset))
{
    @mysql_query("SET NAMES $this->charset");
}

這樣就 ok 了,如果使用 mysqli 請如法炮製。另外如果主機環境符合,可使用 PHP 內建函式來設定:


// PHP >= 5.2.3,MySQL >= 5.0.7 for mysql
@mysql_set_charset($this->charset, $this->conn_id);
// PHP >= 5.0.5,MySQL >= 5.0.6 for mysqli
@mysqli_set_charset($this->conn_id, $this->charset);

PHP, 程式筆記 , , ,