目录
初探 Swoole -- 用 Swoole 启动一个 hello world
内存的妙用 -- PHP终于可以 vs JAVA啦
初级应用 -- 实现用户登录 [撰写中]
展望 -- Swoole 的局限性分析及我个人的期待 [撰写中]
回顾
上节内存的妙用 -- PHP终于可以 vs JAVA啦中, 我们了解了 Swoole 的MYSQL数据库 CURD 操作, 这节我们用 MongoDB来做演示.
开搞
环境说明:
MacOS X El Captain 10.11.6
PHP 7.0.8 with MongoDB support
MongoDB 1.1.8
CSS框架 Bootstrap3
首先, 我们来做个用户登录页面/tpl/login.html
<!DOCTYPE html>
<html>
<head>
<title>Login</title>
</head>
<body>
<form action="/dologin/" method="POST">
<h1>Login</h1>
Username: <input type="text" name="username" id="username"><br/>
Password: <input type="password" name="password" id="password"><br/>
<button type="submit">Submit</button>
</form>
</body>
</html>
PHP代码
我们引入MongoDB
<?php
class Mongo{
static $db = null;
static $dbname = null;
public static function instance($dbname = 'db'){
if (null === self::$db) {
$m = new MongoDB\Client('mongodb://localhost:27017');
self::$db = $m->selectDatabase($dbname);
self::$dbname = $dbname;
}
return self::$db;
}
public static function id($id){
return new MongoDB\BSON\ObjectID($id);
}
public function __call($name, $arguments){
return self::$db->selectCollection(self::$dbname, $name);
}
}
Swoole启动代码
<?php
$http = new swoole_http_server('0.0.0.0', 1688, SWOOLE_BASE);
#使用内存 SESSION~~
$http->_GLOBAL_SESSION = [];
$http->mongo = Mongo::instance('db');
$http->db = new \stdClass();
# 使用预加载, 提前将用户数据加载到内存. 登录都无需网络/磁盘IO
if('user'){
echo "加载用户数据\n";
$http->db->user = [];
$users = $http->mongo->user->find([]);
foreach ($users as $i => $user) {
$user['_id'] = $user['_id']->__toString();
$http->db->user[$user['username']] = $user;
}
echo "用户数据加载完成\n\n";
unset($user);unset($users);
}
主逻辑:
<?php
$http->on('request', function(swoole_http_request $req, swoole_http_response $res) use($http) {
if (!isset($req->cookie) || !isset($req->cookie['sid']) || !$req->cookie['sid']) {
$req->cookie['sid'] = md5(password_hash(time().mt_rand(100000, 999999), 1));
$res->cookie('sid', $req->cookie['sid'], time() + 60 * 60 * 24 * 365 * 10, '/', '', false, true);
}
$_SESS_ID = $req->cookie['sid'];
if (!is_array($http->_GLOBAL_SESSION[ $_SESS_ID ])) $http->_GLOBAL_SESSION[ $_SESS_ID ] = [];
$_SESSION = &$http->_GLOBAL_SESSION[ $_SESS_ID ];
if ( $req->server['request_uri'] == '/' ) {
$res->status(302);
$res->header('Location', '/login/');
$res->end();
return;
}else
if ( $req->server['request_uri'] == '/login/' ) {
if ($_SESSION['user']) {
$res->status(302);
$res->header('Location', '/i/');
$res->end();
return;
}
$html = file_get_contents(dirname(__FILE__).'/tpl/'.'login.html');
$res->write($html);
$res->end();
unset($html);
return;
}else
if ( $req->server['request_uri'] == '/dologin/' ) {
$user = $http->db->user[$req->post['username']];
if (!$user || !password_verify($req->post['password'], $user['password'])) {
$res->write('bad_account_or_password');
$res->end();
return;
}
$_SESSION['user'] = $user;
unset($user);
$res->status(302);
$res->header('Location', '/vul/');
$res->end();
return;
}else
if ( $req->server['request_uri'] == '/i/' ) {
$res->write('You currently logged in as'.$_SESSION['user']['username']);
$res->end();
return;
}
$res->status(404);
$res->end();
return;
});
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。