看标题,微信cookie丶session的使用,应该很喜悦。可是,当我尝试使用cookie和session的时候,他们都失效了。cookie的慢一步,session的实时性,微信都有。可是微信的cookie和session只在当前会话中有效,这个和传统的cookie和session不同的。所以,微信cookie丶session的使用失败了。
现在想一想,为什么要使用cookie或session呢,还不是为了要存储一些有意义的值。不得已,我只好用数据库来代替cookie或session了。对PHP,我只会简单的,使得我封装都做得不好。但,实现功能是做到了。
下边,给出一个需要这种状况的环境。

微信公众号上,我做了一个答题游戏。一共有10道题,每个题目10分。答对得10分,打错得0分。你引导用户去答题。这个时候你需要记录用户当前答题到了第几题,用户得了多少分,以及用户的opendId。因为用户没发送一个消息过来,所有的会话都是新的。程序本身,是不会给你存储什么的。在这个环境下,你就得想办法存储这些值。上边说了cookie和session都不行的。这里,我用了数据库
说个话外题。订阅号以及没用认证的服务号,都没有高级接口权限。使得我们不能知道用户的昵称等信息。只想说,服务号比订阅号有更多的权限接口。不过,也心安了。还是要点不同吧。

下边,就以我自己的上边假设的环境,来完成其功能吧。
建表:
在表中,我们需要创建用户的’OpenId‘的字段,这个就是用户发送过来消息中的’FromUserName‘。还需要当前第几题的字段,以及创建所得分数的字段。为了更好的扩展,还要创建游戏类型的字段,以及创建一个状态值字段。状态值,可以不需要。不过,多个游戏的时候,游戏类型字段是需要的。
表截图如下:


下边来分析下,该怎么写这个答题程序。我把这个游戏程序封装在一个叫GameOne的类中。
为了方便管理,我将选择游戏,以及用户回复答案分开。选择用户用Start接口,回复答案用SendAnswer接口。当用户选择一种游戏后,你得记录下来,并将数据复位。对于一个表,没添加的时候,里边是空的。没有数据。所有的数据,有个中心点,那就是用户的openId。先检查表是否为空。如果为空,存储用户的openId,游戏类型,复位数据。如果表不为空,检查表中是否存储了有该OpenId的数据。如果没有,也一样,存储用户的openId,游戏类型,复位数据。如果有,只需要更新复位就可以了。做好这些之后,你还要给用户推送消息。就是出题目,让用户来答。当然,这个是从第一题开始提问的。至于推送给用户消息,得用到其他类。先不管

上边这些做好了,游戏就开始了。用户发送过来一个答案,我们进入SendAnswer接口。也是一样,这个时候我们还得判断数据库。假如表是空的,说明用户没有选择游戏类型,就直接回复ABCD了。(这里,对于用户发送什么我们管不着。对于程序,只知道答案ABCD。程序看到有ABCD了,就会进入SendAnswer接口。如果用户没有选择游戏,这样的操作,明显是不合理的。这个时候,你可以提醒用户选择游戏,或自动回复一些趣味问题)这个时候,我直接返回了。如果表不为空,而表中没有该用户的OpenId,这个时候,同样是不合理的。返回。如果表中有用户OpenId,但step字段(存储用户回答到第几题)为0(设置为0的时候,是因为用户完成了一轮回答。选择游戏重置的时候,这个值会变成1)时,同样不合理。返回。这上边的三种情况,都是用户没有选择游戏,而直接回复ABCD造成的。所以,我都返回了。并以趣味问题回答给用户。

如果step是其他值,表示用户正在游戏中了。

下边对游戏类容进行封装。为了更方便的使用数据,我们建立四个数组。
第一个数组:$questionList,这个用来存储问题的。它是一个二维数组。之所以要用二维数组,是因为多用性。你可以创建好几种类型的题目(每个类型的里边有很多道题目)。
第二个数组:$resultList,这个用来存储问题的答案的。同样,它也会是一个二维数组。
第三个数组:$singleScoreList,这个用来存储每种类型题目的一个小题目单个得分数目。它是一个一维数组。为什么呢。假如总分是100分,而类型不同,题目个数不一定相同。所以单个题目的得分也会是不同的。
第四个数组:$qusetionNameList,这个用来存储类型题目的名字的。同样,这个也是一个一维数组。

因为这个是针对微信公众平台的。所以还得有个数组,用来记录用户的一些信息。比如用户的OpenId,用户发送的内容。不过,这个数组的值,直接来源于Start函数,它从其参数中获得值。

最后还得准备一个数组,用来存储题目的当前类型,当前题目的步骤(就是答题到第几题),以及你当前所得的分数。

就这么多吧。呃 汗,貌似都是数组。

一步一步的流程,就请直接看代码吧:

<?php
define(DB_HOST , "localhost");
define(DB_USER, "root");
define(DB_PWD,"123456");
define(DB_NAME , "weixin");

class GameOne 
{

    /**
     * 游戏的类型,这里先规定好。0 为人物,1为历史。对应数据库中表的type。
     */
    var $sourceArray;  //原来的用户发送过来的源数据
    var $arrayResult; //返回用户的结果有三个值,type=>是在答哪种题目,step=>进行到第几步了,score=>你的分数;
    var $qusetionNameList = array(0=>"人物" , 1=>"历史");
    var $singleScoreList = array( 0 =>10 ,1=>10);
    var $resultList = array(0 => array("B","C","C","D","A","A","A","D","C", "A"),1 => array("A","A","A","B","A","B","B","B","C","B"));
    var $questionList = array(0=>array(
            "朱安是谁的原配\nA.徐志摩\nB.周树人\nC.周作人\nD.俞大维\n\n亲,请选择答案,回复A、B、C、D,不分大小写",
            "十年一觉迷考据,赢得红楼梦魇名,指的是\nA.刘心武\nB.周汝昌\nC.张爱玲\nD.俞平伯\n\n亲,请选择答案,回复A、B、C、D,不分大小写",
            "重访边城的作者是\nA.沈从文\nB.黄永玉\nC.张爱玲\nD.张恨水\n\n亲,请选择答案,回复A、B、C、D,不分大小写",
            "在我国最早提出学术的【唯此独立之精神,自由之思想】都是\nA.郭沫若\nB.王国维\nC.梁启超\nD.陈寅恪\n\n亲,请选择答案,回复A、B、C、D,不分大小写",
            "民盟中提出从乡村入手改变中国教育的是\nA.陶行知\nB.梁漱溟\nC.张澜\nD.沈钧儒\n\n亲,请选择答案,回复A、B、C、D,不分大小写",
            "胡兰成的原配是\nA.玉凤\nB.张爱玲\nC.佘爱珍\nD.四小姐\n\n亲,请选择答案,回复A、B、C、D,不分大小写",
            "张爱玲翻译过哪部小说\nA.老人与海\nB.红玫瑰与白玫瑰\nC.仲夏夜之梦\nD.指环王\n\n亲,请选择答案,回复A、B、C、D,不分大小写",
            "陆小曼和徐志摩的证婚人是\nA.梁思成\nB.梁思礼\nC.梁思永\nD.梁启超\n\n亲,请选择答案,回复A、B、C、D,不分大小写",
            "冰心曾以《太太的客厅》来讽刺\nA.金岳霖\nB.陆小曼\nC.林微因\nD.张幼仪\n\n亲,请选择答案,回复A、B、C、D,不分大小写",
            "译莎巨匠是指\nA.朱生豪\nB.宋清如\nC.沈从文\nD.傅雷\n\n亲,请选择答案,回复A、B、C、D,不分大小写"
    ),
    1=>array(
            "“大珠小珠落玉盘”所形容的是什么乐器的弹奏声\nA.琵琶\nB.古筝\nC.扬琴\n\n亲,请选择答案,回复A、B、C,不分大小写",
            "《孔雀东南飞》里,刘兰芝'十三能织素,十四学裁衣,十五弹箜篌,十六诵诗书',请问,'箜篌'是什么乐器:\nA.拨弦乐器\nB.击弦乐器\n\n亲,请选择答案,回复A、B,不分大小写",
            "'有板有眼'的'板'是我国传统音乐节奏中的\nA.强拍\nB.弱拍\n\n亲,请选择答案,回复A、B,不分大小写",
            "我们常说'隔着门缝看人',当我们隔着门缝看人时,看到的人\nA.比原来扁了\nB.和原来一样\nC.比原来宽了\n\n亲,请选择答案,回复A、B、C,不分大小写",
            "在古代,'爵'是一种什么器皿\nA.食器\nB.酒器\n\n亲,请选择答案,回复A、B,不分大小写",
            "'白雪公主'这个形象最早来自于\nA.格林童话\nB.安徒生童话\nC.伊索寓言\n\n亲,请选择答案,回复A、B、C,不分大小写",
            "在'精卫填海'的故事里,'精卫'是\nA.一个人\nB.一只鸟\nC.一只猴子\nD.一条龙\n\n亲,请选择答案,回复A、B、C、D,不分大小写",
            "王昭君没有得到汉元帝的召见而远嫁匈奴单于,是因为\nA.王妃对她的陷害\nB.画师歪曲她的形象\nC.大臣说她的坏话\n\n亲,请选择答案,回复A、B、C,不分大小写",
            "安徒生童话《海的女儿》里,小美人鱼变成人是为了见到谁\nA.渔夫\nB.皇后\nC.王子\n\n亲,请选择答案,回复A、B、C,不分大小写",
            "唐代人可以称‘父亲’为\nA.伯伯\nB.哥哥\n\n亲,请选择答案,回复A、B,不分大小写"
    )
    );

    public function Start($array)
    {
        
        $type = array_search($array['Content'] , $qusetionNameList);
        
        $userId = $array['FromUserName'];
        
        $this ->sourceArray = $array;
        
        $id=mysql_connect(DB_HOST,DB_USER,DB_PWD);
        mysql_select_db(DB_NAME,$id);
        mysql_query("set character set utf8");
        
        $num = mysql_num_rows(mysql_query("SELECT * FROM weixin_vinifly",$id))+1;
        
        if($num ==1)
        {
            $sql = "INSERT INTO weixin_vinifly(`id`,`user_id`,`status`,`type`,`step`,`score`) VALUES ($num,'$userId',1,$type,1,0)";
            mysql_query($sql,$id);
            mysql_close($id);    
            $this ->arrayResult = array('type'=>$type , 'step'=>1,'score'=>0);
        }
        else 
        {
            $sql = "SELECT `type`,`step`,`score` FROM `weixin_vinifly` WHERE `user_id`='$userId'";
            $info = mysql_query($sql);
            $tempnum = mysql_num_rows($info);
            if($tempnum ==0)
            {
                $sql = "INSERT INTO weixin_vinifly(`id`,`user_id`,`status`,`type`,`step`,`score`) VALUES ($num,'$userId',1,$type,1,0)";
                mysql_query($sql,$id);
                mysql_close($id);
                $this ->arrayResult = array('type'=>$type , 'step'=>1,'score'=>0);
            }
            else 
            {
                $sql = "UPDATE weixin_vinifly set type = $type , step = 1, score = 0 WHERE user_id ='$userId'";
                mysql_query($sql);
                mysql_close($id);
            }
        }
        
        $str = "答题闯关介绍:根据问题选择正确的答案,每道题只有一个正确答案,回复字母A、B、C、D即可。答题结束自动打分,每道题只能回复一次哦。复位请输入游戏类型名:比如'人物'\n\n";
        $str = $str."答题开始啦:\n\n";
        
        $str = $str.">>>请听第1题<<<\n\n".($this->questionList[$type][0]);
        $this->sourceArray['Content'] =$str;
        $textUtils = new TextUtils();
        $textUtils->BackSameText($this->sourceArray);    
    }
    
    public function SendAnswer($array)
    {
        $textUtils = new TextUtils();
        
        $userId = $array['FromUserName'];
        
        $array['Content'] = strtoupper($array['Content']);
        $this ->sourceArray = $array;
        
        $id=mysql_connect(DB_HOST,DB_USER,DB_PWD);
        mysql_select_db(DB_NAME,$id);
        mysql_query("set character set utf8");
        
        $num = mysql_num_rows(mysql_query("SELECT * FROM weixin_vinifly",$id))+1;
        
        if($num ==1)
        {
            $this->sourceArray['Content'] = '这样是错误的';
            $textUtils ->BackTransitionText($this->sourceArray);
            mysql_close($id);
            return;
        }
        else 
        {
            $sql = "SELECT `type`,`step`,`score` FROM `weixin_vinifly` WHERE `user_id`='$userId'";
            $info = mysql_query($sql);
            $tempnum = mysql_num_rows($info);

            if($tempnum ==0)
            {
                $this->sourceArray['Content'] = '这样是错误的';
                $textUtils ->BackTransitionText($this->sourceArray);
                mysql_close($id);
                return;
            }
            else 
            {
                $row = mysql_fetch_assoc($info);
                $this ->arrayResult = array('type'=>$row['type'] , 'step'=>$row['step'],'score'=>$row['score']);
                
                if($this ->arrayResult['step'] ==0)
                {
                    $this->sourceArray['Content'] = '这样是错误的';
                    $textUtils ->BackTransitionText($this->sourceArray);
                    mysql_close($id);
                    return;
                }
            }
            $this ->backAnswer();
        }
    }
    
    private function backAnswer()
    {
        if($this->sourceArray['Content'] == $this ->resultList[$this->arrayResult['type']][($this->arrayResult['step'] -1)])
        {
            $score = ($this->arrayResult['score'] + $this->singleScoreList[$this->arrayResult['type']]);
            $str = "恭喜,回答正确啦!\n";
        }
        else
        {
            $score = $this->arrayResult['score'] ;
            $str = "呃……貌似选得不太对哦!\n正确答案是:".$this ->resultList[$this->arrayResult['type']][($this->arrayResult['step'] -1)]."\n";
        }

        $str = $str."你已得到分数:".$score."\n\n";
        
        $this->arrayResult['step'] +=1;
        $step = $this->arrayResult['step'];
        
        if($step >= (count($this->questionList[$this->arrayResult['type']]) +1))
        {
            $this->arrayResult['score'] = $score;
            $step = 0;
            $score = 0;
            $this->arrayResult['step'] = 0;
        }
        
        $userId = $this->sourceArray['FromUserName'];
        $sql = "UPDATE weixin_vinifly set step = $step, score = $score WHERE user_id ='$userId'";
        mysql_query($sql);
        mysql_close();
        $this -> nextQuestion($str);
    }
    
    private function nextQuestion($str)
    {
        $this->sourceArray['Content'] = $str;
        $textUtils = new TextUtils();
        $step = $this->arrayResult['step'];
         
        if($step == 0)
        {
            $str = $str."答题游戏结束\n答题分数:".$this->arrayResult['score'];
            $this->sourceArray['Content'] = $str;
            $textUtils->BackSameText($this->sourceArray);
            return;
        }
        $str = $str.">>>请继续听第".$step."题<<<\n\n";
        $str = $str.$this->questionList[$this->arrayResult['type']][$step -1];
        $this->sourceArray['Content'] = $str;
        $textUtils->BackSameText($this->sourceArray);
    }
    
    /**
     * 打印数据到本地
     **/
    private function writeStr($str)
    {
        $date = date('Y-m-d');
        $open=fopen("log/".$date."_log.txt","a" );
        fwrite($open,$str);
        fclose($open);
    }
}
?>

 

有兴趣的朋友,可以关注我微信哦:vinifly