最近两个人合作(一前端一后台)共同写了一个纳新的小系统,过程中遇到了不少的小问题。想法和思路很好,可是有的地方细节和操作还不够到位。
考虑到做这个东西时间问题,还有项目的工程量问题,我们俩不约而同决定不使用框架去实现,我用原生php他用原生JS+JQ。
首先商量了一下,确定了一下功能分块,分为四个大模块:试题模块,查询模块,管理模块,用户个人模块。
试题模块:开始做的是在线答题模块(目前仅支持选择填空),在管理模块,管理员可以通过表单上传试题(Upload_Subject),后台接收到post数据,通过标识符分割字符串,获取到题目(subject)、正确答案(correct)、A、B、C、D四个选项(as_a,as_b,as_c,as_d),上传到数据库;进入在线答题模块后,点击开始答题按钮,前端会执行隐藏该按钮操作,然后通过AJAX向后台请求题库,后台通过(Get_subject)查询数据库,将结果集存入二维字符数组进行JSON_ENCODE,返回给前端;待用户答完题后,将成绩统计后与用户ID一同发回给后台,同时后台进行合法判断成功后更新数据库;
public function Upload_Subject(){
$str = $_POST['textarea_text'];
$matches = explode("|",$str);
$subject = $matches[1];
$correct = $matches[6];
$as_a = $matches[2];
$as_b = $matches[3];
$as_c = $matches[4];
$as_d = $matches[5];
$sql = 'insert into subject_bank(subject,correct,as_a,as_b,as_c,as_d) value(\''.$subject.'\',\''.$correct.'\',\''.$as_a.'\',\''.$as_b.'\',\''.$as_c.'\',\''.$as_d.'\') ';
if($query = mysql_query($sql)){
echo "<script>alert('提交成功!');history.go(-1);</script>";
}
}
public function Get_Subject(){
$sql = 'select distinct suj_id,subject,correct,as_a,as_b,as_c,as_d from subject_bank order by rand() limit 30';
$query=mysql_query($sql);
if($query) {
$temp=array();
while($res=mysql_fetch_row($query)){
$temp[]=$res;
}
echo json_encode($temp);
}
else{
echo "<script>alert('题库获取失败!')</script>";
}
}
状态查询模块:进入状态查询模块后,JS会向后台发送AJAX请求状态数据,后台(Get_State)接收到请求从数据库通过用户ID查询到用户当前面试进度(0,1,2,3)状态,然后返回给前端;
public function Get_State(){
$username = $_SESSION['realname'];
$sql = 'select state from user_msg where name = \''.$_SESSION['realname'].'\'';
if($query = mysql_query($sql)){
if($query = mysql_query($sql)){
$rows = mysql_num_rows($query);
$result = mysql_fetch_assoc($query);
if($rows < 1){
echo "<script>alert('123')</script>";
}
else if($result['state'] == 0){
$str = 0;
echo json_encode($str);
}
else if($result['state'] == 1){
$str = 1;
echo json_encode($str);
}
else if($result['state'] == 2){
$str = 2;
echo json_encode($str);
}
else if($result['state'] == 3){
$str = 3;
echo json_encode($str);
}else{
$str = 9;
echo json_encode($str);
}
}
}
}
管理模块:在进入主页面之前,会进行一次身份的判断,是用第三方认证oauth协议实现的,根据返回的用户组别类型,若是管理员,则直接返回该模块样式给前端,进入管理模块,否则无法进入。管理员进入管理模块可以进行以下操作:按学号查找学生纳新状态信息、加载并浏览所有学生状态概况、修改学生状态。同理都是用AJAX实现的功能。
public function Get_More_Msg(){
$sql = 'select distinct name,sid,point,state from user_msg';
$query = mysql_query($sql);
if($query) {
$temp=array();
while($res=mysql_fetch_row($query)) {
$temp[]=$res;
}
echo json_encode($temp);
}
else{
$str = 1;
echo json_encode($str);
}
}
public function Check_Admin(){
//管理员列
$flag = 0;
//检查标志
if($_SESSION['group'] == "member")
$flag = 1;
if($flag == 1){
echo "样式在此";
}
else echo null;
public function Find_User(){
//智邮社区获取
if(isset($_SESSION['realname']))
$str = $_SESSION['realname'];
else if(isset($_SESSION['username']))
$str = $_SESSION['username'];
else $str = "who are you?";
echo json_encode($str);
}
OAUTH2.0认证
首先登录时要先请求Login方法
public function Login(){
$client_id = '';
$secret = '';
$url = 'http://zypc.xupt.org/oauth/authorize?client_id='.$client_id.'&response_type=code&redirect_uri=http%3A%2F%2Fnaxin.xupt.org%2Fnew%2Foauth.php&secret='.$secret;
header("Location:".$url);
exit();
}
在oauth.php文件中获取到返回的必要信息后,将信息存入SESSION方便使用。
//oauth.php
<?php
$client_id = '';
$secret = '';
$code = $_GET["code"];
$get_token_url = 'http://zypc.xupt.org/oauth/token';
$post_data = 'grant_type=authorization_code&code='.$code.'&redirect_uri=http%3A%2F%2F127.0.0.1%2Fnew%2Foauth.php';
$ch = curl_init();
curl_setopt($ch,CURLOPT_URL,$get_token_url);
curl_setopt($ch,CURLOPT_HEADER,0);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1 );
curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 10);
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, $post_data);
curl_setopt($ch, CURLOPT_HTTPAUTH, CURLAUTH_BASIC);
curl_setopt($ch, CURLOPT_USERPWD, $client_id.':'.$secret);
$res = curl_exec($ch);
curl_close($ch);
$json_obj = json_decode($res,true);
$access_token = $json_obj['access_token'];
$get_user_info_url = 'http://zypc.xupt.org/oauth/userinfo?access_token='.$access_token.'&client_id='.$client_id.'&secret='.$secret;
$ch = curl_init();
curl_setopt($ch,CURLOPT_URL,$get_user_info_url);
curl_setopt($ch,CURLOPT_HEADER,0);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1 );
curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 10);
$res = curl_exec($ch);
curl_close($ch);
$user_info = json_decode($res,true);
$_SESSION['username'] = $user_info['username'];
$_SESSION['sex'] = $user_info['sex'];
$_SESSION['group'] = $user_info['group'];
if($_SESSION['group'] == "student")
$_SESSION['realname'] = $user_info['realname'];
$_SESSION['student_no'] = $user_info['student_no'];
header('Location:../4.0/join.html');
获取到必要信息后,前端最终会向后台再次发送一个身份认证,判断用户身份。
public function Sign_in(){
if($_SESSION['group'] == "member"){
header("location:../4.0/index.html");
}
else if($this -> Check_SignIn() == 0){
$sid = $_SESSION['student_no'];
$username = $_SESSION['realname'];
if($sid != ""||$username != ""){
$sql = 'insert into user_msg(sid,name) value(\''.$sid.'\',\''.$username.'\')';
if($query = mysql_query($sql)){
header("location:../4.0/index.html");
exit();
}
}else{
echo "<script>alert('未找到登录信息!');history.go(-1);</script>";
}
}else{
header("location:../4.0/index.html");
exit();
}
}
至此登陆成功。
过程中有几点问题需要注意:
1. header()之前不能有输出。
2. 如果没有设置session_auto_start=1的话,需要在php文件顶部加上session_start()。
3. php文件结尾标识符 ?> 的问题,若是前后端分离最好不要加?>,避免输出不必要的空格或空行;若是php、html混编?>是必要的,避免报错。
4. 组合sql语句时,注意灵活使用\转义单引号。