3.3 后台开发侧记(php+smarty,jQuery,layer)

目录

1.发模板消息时两个重要方法的实现

(1)getAccessToken的实现

(2)request_post的实现

2.后台两个简单的页面实现

(1)后台用户管理页面

(2)后台课程管理页面


在本章的开发过程中,我们建立了一个简单的后台系统,一个是希望对人员进行管理(主要完成人员身份的设置)。在前端,不同身份(教师还是学生)可以操作的界面是不同的,教师可以领取教学任务,而学生能够选择已有教师领取任务的课程。

我们还对课程进行管理维护,目的是统计可以开课的课程信息。如果有教师领取了该课程的教学任务,同时有学生选择了这门课程,该课程还尚未开课,此时可以对课程进行开课。后台点击开课按钮时,即触发上节提到的轮询向选择了该门课程的同学发送开课模板信息。

1.发模板消息时两个重要方法的实现

(1)getAccessToken的实现

在实现getAccessToken时,与第二章不同。第二章是需要用户授权获得页面code,之后通过页面code换取网页授权access_token。而在本章,由于向已关注公众号的用户发送模板消息时,该用户的wxid已经知道,我们只需要微信公众平台上已有的appID和appSecret两个参数获得后台发送消息、处理事件的普通access_token即可。(参考 网页授权 | 微信开放文档 中“关于网页授权access_token和普通access_token的区别”的说明)。

按照微信开发文档中关于普通access_token获取说明

(https://developers.weixin.qq.com/doc/offiaccount/Basic_Information/Get_access_token.html),接口调用请求地址格式为:

https请求方式: GET

https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=APPID&secret=APPSECRET

其中,参数grant_type是固定的,填写client_credential,而appid和appsecret在第二章时介绍过,应在微信开放平台后台可以看到的。

调用成功后,该接口返回一个json字符串,格式为:

{"access_token":"ACCESS_TOKEN","expires_in":7200}

还需注意的是,access_token有7200秒的有效期,即无需重复调用该接口,使用上次获取的,处于有效期内的access_token就可以完成需要access_token程序中。

鉴于此,本文中,将调用后的access_token和有效期、获取时间等存放在数据库中,下次需要使用时,根据当前时间计算是否过期,未过期的情况下不再重复调用。

数据表的实现

CREATE TABLE `sys_config_temp` (
  `ID` int(11) NOT NULL AUTO_INCREMENT,
  `access_token` varchar(200) DEFAULT NULL,
  `expires_in` int DEFAULT NULL,
  `receiveTime` int DEFAULT NULL,
  PRIMARY KEY (`ID`) USING BTREE
) ENGINE=InnoDB AUTO_INCREMENT=17 DEFAULT CHARSET=utf8 ROW_FORMAT=DYNAMIC;

INSERT INTO `sys_config_temp` VALUES(1,"non-receive",7200,1680665312);

后台调用代码的实现

function getAccessToken($appid,$appsecret)
	{
		
		$access_token = $back->GetAccessToken();
		if($access_token == 'non-receive') // 未获取或已超时
		{
            //构造接口格式重新获取
			$url = "https://api.weixin.qq.com/cgi-bin/token?
grant_type=client_credential&appid=$appid&secret=$appsecret";
			$result = $this->_https_request($url);
			$jsoninfo = json_decode($result, true);
			$access_token = $jsoninfo['access_token'];
			$expires_in = $jsoninfo['expires_in'];
			// 向数据库中更新
			$back->UpdateAccessToken($access_token,$expires_in);
		}

		return $access_token;
	}

在back.class.php中实现上述辅助的数据库操作为:

function GetAccessToken()
	{
		$sql = "SELECT * FROM sys_config_temp WHERE ID=1";
		$query = $this->query($sql);
		$access_token = "non-receive";
		if($query->num_rows!=0){
			$row = $this->fetch_array($query);
			$rec_Time = $row['receiveTime'];
			$exp_Time = $row['expires_in'];
			$now_Time = time();
			// 如果没有超时则使用数据库中的access_token
			if($now_Time-$rec_Time<$exp_Time)
			{
				$access_token = $row['access_token'];
			}
		}
		return $access_token;
	}

	function UpdateAccessToken($aToken,$expires)
	{
		$now_Time = time();
		$sql = "UPDATE sys_config_temp SET 
receiveTime=$now_Time,access_token='$aToken',
expires_in=$expires WHERE ID=1";
		return $this->query($sql);
	}

(2)request_post的实现

请注意curl的参数设置,设置错误时微信服务器不能正确返回数据。

function request_post($url = '', $param = '') {
		if (empty($url) || empty($param)) {
			return false;
		}
		
		$postUrl = $url;
		$curlPost = $param;
		$ch = curl_init();//初始化curl
		curl_setopt($ch, CURLOPT_TIMEOUT, $this->curl_timeout);
		curl_setopt($ch, CURLOPT_URL, $postUrl);   // 提交地址
		curl_setopt($ch, CURLOPT_SSL_VERIFYPEER,FALSE);
		curl_setopt($ch, CURLOPT_SSL_VERIFYHOST,FALSE);	
		curl_setopt($ch, CURLOPT_HEADER, FALSE);
		curl_setopt($ch, CURLOPT_RETURNTRANSFER, TRUE);
		curl_setopt($ch, CURLOPT_POST, 1);//post提交方式
		curl_setopt($ch, CURLOPT_POSTFIELDS, $curlPost); // 数据内容(模板参数)
		$data = curl_exec($ch);//运行curl	
		curl_close($ch);		
		return $data; // 返回执行结果
	}

2.后台两个简单的页面实现

(1)后台用户管理页面

 这里我们使用了基于PHP的一个著名的引擎模板smarty,它的作用是将前端html和后端php分离,而不是在php文件中嵌入html。

在users.php中,我们使用下述方式完成模板赋值和显示:

// 查询所有人员
$user_list = $back->queryUsers();
// 隐私脱敏
foreach($user_list as $i => $item)
{
	$user_list[$i]["u_name"] =substr_cut($user_list[$i]["u_name"]);
	$user_list[$i]["u_wxid"] =substr_cut($user_list[$i]["u_wxid"]);
	$user_list[$i]["u_mobile"] =substr_cut($user_list[$i]["u_mobile"]);
}
// 赋值给模板
$smarty->assign('user_list',$user_list);
$smarty->assign('cur', 'users');

$smarty->display('users.html');

在模板文件users.html中,按照smarty的使用方式,我们有

<tbody id="tableText">
	<!-- {foreach from=$user_list item=user} -->
    <tr class="odd gradeX">
    <td><input type="checkbox" name="chk[]" value="{$user.u_id}"></td>
    <td>{$user.u_id}</td>
    <td>{$user.u_name}</td>
    <td>{$user.u_mobile}</td>
    <td>{$user.u_wxid}</td>
    <td><!--{if $user.u_type eq 1}-->
    教师<!--{else}-->学生<!--{/if}--></td>
	<td align="center"><button type="button" class="btn btn-primary" 
onclick="openlayer({$user.u_id})">修改</button> 
| <button type="button" class="btn btn-warning" 
onclick="delconfirm({$user.u_id})">删除</button></td>
   </tr>
   <!-- {/foreach} -->
</tbody>

这里,我们还使用了基于jQuery的ajax技术,在处理“修改”和“删除”时,我们不再刷新整个页面,而是通过ajax异步获取后台数据,只刷新tbody部分内容。

// 弹出层,确定删除对话框
layer.confirm('确定删除?',
{
	icon:7,
	title:'删除人员',
	btn:['确定','取消']
},function(){
	$.ajax({
       url: 'https://www.XXX.cn/classBack/interface',
       data:{op:'delUser'
       uid:uid},
       type: 'POST',
       dataType: 'json',
       success: function (result) {
					
          var data = result.data;
          if (data) {
                        
           var str = "";//把数据组装起来
           for (var i = 0; i < data.length; i++) {
			str += "<tr class=\"odd gradeX\"><td>
<input type=\"checkbox\" name=\"chk[]\" value=\""
 + data[i].u_id + "\"></td>";
            str += "<td>" + data[i].u_id +
            "</td><td>" + data[i].u_name +
            "</td><td>" + data[i].u_mobile +
           "</td><td>" + data[i].u_wxid;
			if (data[i].u_type==1)
			{
				str += "</td><td>教师</td>";
			}
			else
			{
				str += "</td><td>学生</td>";
			}
			str += "<td align=\"center\">
<button type=\"button\" class=\"btn btn-primary\" 
onclick=\"openlayer(" 
			+ data[i].u_id + ")\">修改</button> 
| <button type=\"button\" class=\"btn btn-warning\" 
onclick=\"delconfirm("
			+ data[i].u_id  + ")\">删除</button></td></tr>";
                                
       }
//只刷新tbody部分
      $("#tableText").html(str);
	  layer.closeAll('dialog');
   }
                    
},
error: function (err) {
	console.log(err);
                }
 });
			
})

(2)后台课程管理页面

课程管理中值得关注的是计算是否达到开课标准部分,我们在back.class.php中实现了一个queryCourse_st的方法如下:

// 返回课程及开课结果
	function queryCourse_st($c_id)
	{
		$sql = "";
		if($c_id <= 0) // 小于等于0时查询全部课程
		{
			$sql = "SELECT a.*,b.c_state FROM course a 
LEFT JOIN teaching b on a.ID = b.c_ID";
		}
		else
		{
			$sql = "SELECT a.*,b.c_state FROM course a 
LEFT JOIN teaching b on a.ID = b.c_ID WHERE a.ID = $c_id";
		}
		$course_list = array();
		$query = $this->query($sql);
		// 将查询结果转化为数组列表
		while ($row = $this->fetch_array($query)) {
			$course_list[] = array(
				"c_name" => $row['c_name'],
				"c_id" => $row['ID'],
				"c_state" => $row['c_state'],
				"c_credit" => $row['c_credit'],
				"c_teacher" => "",
				"c_stCount" =>0,
				"c_isCanStart"=>0
			);
		}
		// 对每一个查询结果进行判断
		// 判断依据:选课人数>0,教师已选课,课程处于未开课状态
		foreach($course_list as $i => $item)
		{
			$c_item_id = $item["c_id"];
			$t_bSeletion = false;
			$s_bSelection=false;
			$sql = "select a.t_name from teacher a,
teaching b where a.ID=b.t_ID and b.c_id=$c_item_id";
			$query = $this->query($sql);
			if ($query->num_rows!=0)
			{
				$teacher = $this->fetch_array($query);
				$course_list[$i]["c_teacher"] = $teacher["t_name"];
				$t_bSeletion = true;
			}
			$sql = "select count(*) as cn from selection 
where c_id=$c_item_id";
			$query = $this->query($sql);
			if ($query->num_rows!=0)
			{
				$cnum = $this->fetch_array($query);
				$course_list[$i]["c_stCount"] = $cnum["cn"];
				if ( $cnum["cn"] > 0)
					$s_bSelection = true;
			}
			if($t_bSeletion && $s_bSelection && $item["c_state"] ==0)
			{
				$course_list[$i]["c_isCanStart"] =1;
			}
		}
				
		
		// 返回结果列表
		return $course_list;
	}

本章小结

在本章,我们主要通过调用接口获取普通access_token,并通过微信服务号模板消息接口向已选课程的同学发送模板消息。

本章后台使用的基于php的smarty引擎、jQuery的ajax异步刷新技术等,将在后续章节后台不断完善中继续使用,希望大家掌握。

补记:作者是在业余时间开展创作,随着年龄的增长,精力实在有限。前端时间由于工作上的原因,停更的长达2年之久,深表歉意。作者一定怀着对自己喜欢的事业崇敬心情,将本文创作完成!希望得到广大微信公众号开发、H5开发、PHP开发或者其他技术的爱好者的支持和鼓励,请多多关注和支持,我坚信,我不是一个人在战斗!

本章代码,请在此处下载。对本章内容有任何疑问,欢迎在评论区留言!您的鼓励是作者能够继续前行的莫大动力~~

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值