用Slim轻型PHP框架写RESTful APIs

寒假和一同学合作写个网站,他用AngularJS构建前端,我用PHP写RESTful的数据接口,撸到最后也有1000行了,其实我也并不太理解RESTful,看了阮一峰介绍RESTful的博客,简单的说,RESTful架构,就是目前最流行的一种互联网软件架构。它结构清晰、符合标准、易于理解、扩展方便,所以正得到越来越多网站的采用。在那篇博客的结尾阮一峰是这样总结的:

  • 每一个URI代表一种资源
  • 客户端和服务器之间,传递这种资源的某种表现层
  • 客户端通过四个HTTP动词,对服务器端资源进行操作,实现表现层状态转化

我的理解仅仅在最后一点

切入正题Slim,一个PHP的轻型框架,这里是Slim中文文档,还有Slim官网,中文文档里介绍的用Composer进行安装我是没有试过,手动安装也很方便,去Slim的Github上把项目clone下来就OK了。再把项目文件复制到服务器下就可以在浏览器里打开对应的路径就可以看到Slim的欢迎页面。

Slim要求PHP版本大于等于5.3,如果你需要对cookies进行加密,则还需要mcrypt拓展。我们还需要URL重写,所以要启用Apache的mod_rewrite模块,最后配一个虚拟主机,再改个host就可以了。

主要的工作是在项目根目录下的index.php文件里进行的,第一步需要引入Slim框架

1
2
3
4
5
//第一步:引用Slim框架
//首先,需要在你的index.php中引入Slim框架的依赖,根据实际情况,你可能得调整下文件的路径

require 'Slim/Slim.php';
\Slim\Slim::registerAutoloader();

第二步:初始化Slim框架

1
2
3
//第二步:初始化Slim框架

$app = new \Slim\Slim();

第三步:定义路由

这是一个最简单的路由,再打开项目的入口页面,页面会显示经典的Hello World!

1
2
3
4
5
// GET route
$app->get('/', function () {
//do something
echo "Hello World!";
});

这是一个POST请求的路由,我们可以向/post路由POST数据,后端接受并处理后再返回对应的数据

1
2
3
4
5
// POST route
$app->post('/post', function () {
//do something with post data
echo 'This is a POST route';
});

这是一个PUT请求的路由,一般用于数据的更新操作,我们可以向/put路由PUT数据,后端接受并处理后再返回对应的数据

1
2
3
4
5
// PUT route
$app->put('/put', function () {
//do something with put data
echo 'This is a PUT route';
});

一般在执行更新操作时,会有对应的id,比如说我要修改id为3的那条数据时,我们只要向/post/:id路由PUT数据,对应的路由函数就要修改成下面这样:

1
2
3
4
5
// PUT route
$app->put('/put/:id', function ($id) {
//do something with put data and id
echo 'This is a PUT route';
});

这是一个DELETE请求的路由,和之前的PUT路由类似,一般也像PUT一下,会有一个id,再根据对应的id执行相关的操作,代码如下:

1
2
3
4
5
// DELETE route
$app->delete('/delete/:id', function ($id) {
//do something with id
echo 'This is a DELETE route';
});

终于,可以运行程序了,这一步基本上就是index.php中最后执行的了.

1
2
3
//第四步:运行程序

$app->run();

在我的AngularJS入门的小Demo这篇博客中,后端RESTful APIs的代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
<?php
require 'Slim/Slim.php';
$app = new Slim();
$app->get('/book', 'getAllBook');
$app->get('/book/:id', 'getBook');
$app->post('/book', 'addBook');
$app->put('/book/:id', 'updateBook');
$app->delete('/book/:id', 'deleteBook');
$app->run();
function getConnection()
{

$dbhost = "127.0.0.1";
$dbuser = "root";
$dbpass = "";
$dbname = "book";
$dbh = new PDO("mysql:host=$dbhost;dbname=$dbname", $dbuser, $dbpass);
$dbh->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
return $dbh;
}
function getAllBook()
{

$sql = "SELECT id, name, author, press FROM book ORDER BY id ASC";
try {
$db = getConnection();
$stmt = $db->query($sql);
$book = $stmt->fetchAll(PDO::FETCH_OBJ);
$db = null;
echo '{"book": ' . json_encode($book) . '}';
} catch (PDOException $e) {
error_log($e->getMessage(), 3, '../api/php.log');
echo '{"error":{"text":' . $e->getMessage() . '}}';
}
}
function getBook($id)
{

$sql = "SELECT * FROM book WHERE id=:id";
try {
$db = getConnection();
$stmt = $db->prepare($sql);
$stmt->bindParam("id", $id);
$stmt->execute();
$book = $stmt->fetchObject();
$db = null;
echo json_encode($book);
} catch (PDOException $e) {
error_log($e->getMessage(), 3, '../api/php.log');
echo '{"error":{"text":' . $e->getMessage() . '}}';
}
}
function addBook()
{

$request = Slim::getInstance()->request();
$book = json_decode($request->getBody());
$sql = "INSERT INTO book (name, author, press, description) VALUES (:name, :author, :press, :description)";
try {
$db = getConnection();
$stmt = $db->prepare($sql);
$stmt->bindParam("name", $book->name);
$stmt->bindParam("author", $book->author);
$stmt->bindParam("press", $book->press);
$stmt->bindParam("description", $book->description);
$stmt->execute();
$book->id = $db->lastInsertId();
$db = null;
// echo json_encode($book);
} catch (PDOException $e) {
error_log($e->getMessage(), 3, '../api/php.log');
echo '{"error":{"text":' . $e->getMessage() . '}}';
}
}
function updateBook($id)
{

$request = Slim::getInstance()->request();
$body = $request->getBody();
$book = json_decode($body);
$sql = "UPDATE book SET name=:name, author=:author, press=:press, description=:description WHERE id=:id";
try {
$db = getConnection();
$stmt = $db->prepare($sql);
$stmt->bindParam("name", $book->name);
$stmt->bindParam("author", $book->author);
$stmt->bindParam("press", $book->press);
$stmt->bindParam("description", $book->description);
$stmt->bindParam("id", $id);
$stmt->execute();
$db = null;
// echo json_encode($book);
} catch (PDOException $e) {
error_log($e->getMessage(), 3, '../api/php.log');
echo '{"error":{"text":' . $e->getMessage() . '}}';
}
}
function deleteBook($id)
{

$sql = "DELETE FROM book WHERE id=:id";
try {
$db = getConnection();
$stmt = $db->prepare($sql);
$stmt->bindParam("id", $id);
$stmt->execute();
$db = null;
} catch (PDOException $e) {
error_log($e->getMessage(), 3, '../api/php.log');
echo '{"error":{"text":' . $e->getMessage() . '}}';
}
}
?>

OK!Slim用起来还是很方便的,做简单的CRUD操作后端还是非常适合的。

推荐两款Chrome插件,测试RESTful APIs用Postman - REST Client shortcut,还有一个是JSON格式化的插件JSON-handle
Chrome插件截图

Fork me on GitHub