×
广告

一面微信墙的诞生(2) 消息服务端的搭建

96
忠叔
2017.11.22 16:29* 字数 529

上一节:一面微信墙的诞生(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请求进行测试。


图2-1 postman测试结果

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

图2-2 数据库插入结果

数据库中也出现了插入的新数据。

至此,我们完成了从消息服务端写入数据的这一过程。

图2-3 已经实现的部分

下一步,是编写对应的客户端页面,通过界面向服务器发送留言。

下一节:一面微信墙的诞生(3) 用户端界面的创建

附加内容

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,当前参数的数目和顺序需要保持一致,如果有需要可以继续优化这个函数。

一面微信墙的诞生
Web note ad 1