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,我觉得会有一些人会喜欢上的。


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