php,採用slim和notorm搭建Restful輕量級curd服務層,及中文字符解決

轉載請註明:http://blog.csdn.net/langyuewu/article/details/25254729

前言

先前工作,服務層搭建早期我採用wcf實現,再後來wcf實現restful方式以滿足多終端簡單調用,再後來用asp.net webAPI來實現,這也算是一種架構思路的轉變吧。

到現在,開始做一些個人興趣項目,在考慮成本及各方綜合考慮的情況下,打算服務端部署到雲上,現在新浪雲、百度雲、阿里雲就聚集了很多用戶,最開始它們都只支持php和java,後來也開放對nodejs的支持,但對於上述提到過wcf、webAPI等是不支持的,於是只好放棄(雖然我覺得挺優雅的),改用php來實現(後續考慮到推送,可能會採用nodejs,php實現起來太麻煩)。

php也用過,從開源的系統上修修改改幫朋友做了個網站,但用得不多,自認不精(技術越懂得多越不會隨便用精通這個詞了),所以爲了減低工作難度,維護容易,擴展方便,搜索起合適的框架來,最後鎖定了slim+notorm的組合。

簡單介紹

slim是爲了實現restful,基於路由機制,notorm是輕量級orm框架,兩者結合應用挺完美,具體的使用請baidu或google一下。

在這裏提供notorm介紹使用的鏈接:

http://www.sitepoint.com/database-interaction-made-easy-with-notorm/

在我寫完這篇文章,過了一段時間後,翻閱作者的博客,居然看到這篇,剛好是slim+notorm結合的,強烈推薦:

http://www.sitepoint.com/writing-a-restful-web-service-with-slim/?utm_source=tuicool

如果嫌棄慢或打不開,可以打開推酷引用的頁面:

http://www.tuicool.com/articles/qaIVBn

環境搭建

下載源碼包,解壓縮,我個人大致這樣的目錄結構(index.php爲隨意創建的頁面):


打開演示用的Index.php,輸入以下代碼:

require 'Slim/Slim.php';
require 'NotORM.php';

\Slim\Slim::registerAutoloader();
$app = new \Slim\Slim();
$pdo = new PDO("mysql:host=localhost;dbname=test1","root","");
$db = new NotORM($pdo);
$db->exec("SET NAMES 'utf8'");         
$app->get(
    '/',
    function () {
        echo 'Hello Slim';
	}
);

$app->get(
    '/hello',
    function () {
        echo 'Hello Slim';
    }
);

// GET route
$app->get(
    '/data',
    function () use ($app,$pdo, $db){
        echo 'data';
		$homes=$db->homes();  
		foreach ($homes as $home) { // get all applications
			echo $home["title"]; // print home title
		}
	}
);
$app->run();
代碼很好理解,我就不解釋了,三個方法分別可以用以下路徑訪問

網站根目錄/index.php
網站根目錄/index.php/hello
網站根目錄/index.php/dada

問題排解

看,三下五除二,幾分鐘就把後臺簡單搭建起來了,但有個問題困惑了我很久,就是中文字符問題,slim還沒什麼,倒是用上了notorm就出問題了,大多數參考資料都是以下面類似方式調用的:

$pdo = new PDO("mysql:host=localhost;dbname=test1","root","");
$db = new NotORM($pdo);

而我以爲php編碼和數據庫編碼一致就好了(都是設置成utf-8),在php頁面頭加上這段:

header('Content-type: text/html;charset=utf-8');

結果數據庫查詢結果出現了亂碼,我還以爲是notorm的問題,還特意去看了下源碼,後來想到可能是PDO的調用方式,後來找到資料,說PDO的調用方式加上下面這句:

$db->exec("SET NAMES 'utf8'");         

或者下面的也可以

$db->exec("SET character set utf8");   //注意是utf8,不是utf-8

一試成功,至此查詢時的亂碼問題解決了,原理是指定用數據庫一致的字符編碼參數來讀取數據

至於如何查看數據庫的編碼,在mySQL輸入以下命令,如果不是utf8的,請相應改正(曾經遇到過,在Navicat裏設置了數據庫、表和字段的特徵值,但愣是給我返回亂瑪,輸入命令一看

show variables like 'collation_%';
show variables like 'character_set_%'

collation_server是其它編碼的,竟沒有隨庫、表、字段的設置而更改,執行命令或查詢語句修改之:

set collation_database=utf8_general_ci; 

便開始測試插入保存數據的情況,代碼如下(簡單測試用get代替post),

$app->get("/testInsert", function () use ($app,$pdo, $db) {
		//$pdo->query("set names gbk"); 
		$homes = $db->homes();
		$data = array(
		"title" => "notorm測試",
		"author" => "小五"
		);
	$result = $homes->insert($data);
	echo "插入 successfully.";
});
發現插入的是亂碼!什麼情況?取的時候正常,插入時亂碼,暈死了,把註釋去掉後,居然很神奇地可以了!!明明mysql是utf8的,這裏用gbk竟然可以正確插入,這總有問題的,但一時也不知道原因。

後來,服務層搭建完成,到了調用的時候,這個時候用html頁面ajax調用php的服務,發現返回數據是亂碼(瀏覽器直接打開php是正常的),這時終於下定決心完全理清編碼問題,結果搜到這篇文章:

http://bbs.phpchina.com/thread-19514-1-1.html

其中這句引起了我的注意:

“因爲記事本默認的是用ANSI標準保存,而gb2312是其中的一種!對於簡體中文的操作系統,我們存儲的是一段gb2312數據!如果你騙瀏覽器這是一段utf-8的數據,那這個忠實的僕人自然就會犯錯誤了”

若有所悟,再考慮到上述以gbk插入時居然正確的情況,我懷疑是我犯了個低級錯誤(新建記事本,改了擴展名再寫入代碼),使得php的內容保存的是gb2312的格式,實際上我應該把它保存爲UTF-8格式,於是通過NodePad++轉換並保存之,重新ajax調用,正確!把插入時多加的那段$pdo->query("set names gbk");刪掉,插入也正確,至此問題完全解決。


總結,無論是header('Content-type: text/html;charset=utf-8')還是 <meta charset="utf-8">,只是告訴瀏覽器以何種編碼解讀頁面,但是頁面的內容本來就不是該種編碼,就會出現亂碼情況,所以確保網頁編碼和告訴瀏覽器解釋編碼要一致。同樣的,數據庫數據編碼和上述兩種編碼一致,即:

數據庫編碼=瀏覽器解釋編碼=頁面編碼

不然就會出現:

數據庫編碼=瀏覽器解釋編碼!=頁面編碼:讀取數據庫顯示正確,頁面亂碼,插入數據亂碼。

數據庫編碼!=瀏覽器解釋編碼=頁面編碼:頁面顯示正確,讀寫數據亂碼。

數據庫編碼=頁面編碼!=瀏覽器解釋編碼:頁面顯示亂碼,寫數據正確。

也就是說slim+notorm完全沒有問題,只是我用來封裝的服務頁面編碼錯誤,導致繞了些彎路,有興趣想搭建簡單服務層的話可以瞭解下slim+notorm,我覺得會有一些人會喜歡上的。


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