
上一节:一面微信墙的诞生(1) 概述、工具和数据库准备
本项目 github 地址 : https://github.com/heygirlwhatyournameis/wechatwall
消息服务端要处理的事情有两个:一是把用户发过来的数据存的数据库里,二是把数据库里的留言查询出来推送给“墙端”。在本文,我们先处理第一个部分,处理用户传送过来的数据,将它储存在数据库里。
写一个数据库类
在 util 文件夹下建立一个 db.class.php 文件,用于为服务端和用户端提供数据库工具。为了后面开发的方便,我们把它封装成一个简单类。
<?php
<?php
class Db {
private $host;
private $port;
private $username;
private $password;
private $dbname;
private $charset;
public static $instance;
public $connection;
/**
* 使用单例模式
*/
public static function getInstance(){
if(!isset(self::$instance)){
self::$instance=new self();
}
return self::$instance;
}
/**
* 私有构造函数,防止从类外new新实例
*/
private function __construct(){
$this->host='localhost';
$this->port='3306';
$this->username='root';
$this->password='123456';
$this->dbname='wall';
$this->charset="utf8";
$this->connect();
}
/**
* php 7.0移除了旧版mysql API
* 使用增强版 mysqli 来操作数据库
*/
public function connect(){
$this->connection=new mysqli("$this->host:$this->port",$this->username,$this->password,$this->dbname);
//设置编码
$this->connection->set_charset($this->charset);
}
public function query($sql){
return $this->connection->query($sql);
}
/**
* 查询并返回结果集
*/
public function select($sql){
$result=$this->query($sql);
if($result)
return $result->fetch_all(MYSQLI_ASSOC);
return [];
}
/**
* 查询并返回一条结果
*/
public function find($sql){
$result=$this->query($sql);
if($result)
return $result->fetch_array(MYSQLI_ASSOC);
return [];
}
/**
* 执行并返回受影响的行数
*/
public function execute($sql){
$this->query($sql);
return $this->connection->affected_rows;
}
编写留言处理程序
在 server 文件夹新建 new.php 文件:
- 因为还没有写登录程序,所以程序中 $openid 直接赋值为测试使用的 abcdefg,后续将从 session 中读取。
- 注意插入语句中,$openid 和 $content 两个字段需要包裹单引号。
<?php
//创建数据库实例
require('../util/database.class.php');
$db=Db::getInstance();
//通过json返回代码和结果
function result($errorCode,$message){
echo json_encode([
'errorCode'=>$errorCode,
'message'=>$message
]);
}
/**
* 预留使用
* session_start();
* $openid=$_SESSION['wall_open_id'];
*/
$openid='abcdefg';
if(!$openid){
result(1,'未登录');
die;
}
if(!isset($_POST['content'])){
result(2,'消息为空');
die;
}
//处理留言消息
$time=time();
$content=$_POST['content'];
$a=$db->execute("INSERT INTO message VALUES (null,'$openid','$content',$time)");
if($a>0){
result(0,'留言成功');
} else {
result(3,'留言失败');
}
测试
由于还没有写客户端页面,这里使用 postman 工具模拟 post 请求,如果你没有这样的工具,你可以先把 $_POST['content'] 改为 $_GET['content'] 在浏览器使用get请求进行测试。

可以看出返回结果输出了代码0,即插入成功。

数据库中也出现了插入的新数据。
至此,我们完成了从消息服务端写入数据的这一过程。

下一步,是编写对应的客户端页面,通过界面向服务器发送留言。
附加内容
mysqli 支持 prepare+execute 的查询方式,此处提供一种封装好的插入方法,以供参考:
/**
* 执行插入语句
* 返回受影响的函数
*/
public function insert($table,$params){
//构造预处理语句
foreach($params as $key=>$v){
$prepare_str[]="?";
switch(gettype($v)){
case 'integer':$bind_str[]='i';break;
case 'double':$bind_str[]='d';break;
default:$bind_str[]='s';
}
$references[]=&$params[$key];
}
$prepare_str=implode(',',$prepare_str);
$bind_str=implode('',$bind_str);
array_unshift($references, $bind_str);
if($stmt=$this->connection->prepare("INSERT INTO $table VALUES ($prepare_str)")){
//魔法方法,将数组作为参数列表调用函数
call_user_func_array(array($stmt,"bind_param"),$references);
if(!$stmt->execute())
echo $this->connection->error;
}
return $this->connection->affected_rows;
}
使用方法:
$db->insert('message',['id'=>0,'openid'=>$openid,'content'=>$content,'time'=>time()]);
自增的主键设为0,当前参数的数目和顺序需要保持一致,如果有需要可以继续优化这个函数。
网友评论