前天晚上查看天气预报的Cron执行结果时,看到了这个:

SuccessSuccessSuccessSuccessSuccessSuccessSuccessSuccessSuccessFailSuccess

我感到莫名的压力。。。因为实际上这个服务只有11个用户。只有11个用户的服务都无法保证服务质量,这多荒唐。

这时我才发现,原作者的设计实际上是最优的选择。他的设计是,数据库里每一个用户的记录多一个字段today,作为今天是否已经发送的标记。应用是在18:00~18:30每隔几分钟执行一次,而不是在18:00执行一次。运行时,从数据库取出today字段值为0的用户发送短信,发送成功后将这个字段值改为1,直到不存在此字段为0的用户为止。应用的Cron任务有两个,出了18:00~18:30的发送短信以外,每晚00:30有还一次数据库写入,将所有用户的today字段值改为0,以供第二天发送短信时读取。

于是我想到了使用 xml 文件的方式,我可以在 SAE 建立一个 Storage ,将数据放入 xml 文件,保存在那里,使用跟数据库类似的原理进行读写。而且跟方便的是, php 可以用 DOMDocument 读取 xml (虽然我从来没有用过,我的 php 实践只到文件夹扫描为止),这跟 JavaScript 类似,而数据库?从上学期期末数据库设计作业之后我就再也没写过 SQL 语句了。然后我动手写了这么一堆玩意。

<?php
function getCityId($cName){
  $cxml = new DOMDocument('1.0');
  $cxml -> load('citydata.xml');
  $cities = $cxml -> getElementsByTagName('city');
  foreach($cities as $cs){
    $cns = $cs -> getElementsByTagName('name');
    $cis = $cs -> getElementsByTagName('id');
    $cn = $cns -> item(0) -> nodeValue;
    $ci = $cis -> item(0) -> nodeValue;
    if($cn == $cName){
      return $ci;
    }
  }
}

$xml = new DOMDocument();
$xml -> load('userfeed.xml');
$users = $xml -> getElementsByTagName('user');
foreach($users as $user){
  $nicks = $user -> getElementsByTagName('nick');
  $citys = $user -> getElementsByTagName('city');
  $mobiles = $user -> getElementsByTagName('mobile');
  $todays = $user -> getElementsByTagName('today');
  $nick = $nicks -> item(0) -> nodeValue;
  $city = $citys -> item(0) -> nodeValue;
  $mobile = $mobiles -> item(0) -> nodeValue;
  $today = $todays -> item(0) -> nodeValue;
  if($today == 0){
    $cityId = getCityId($city);
    $tomorrow = getWeatherData($cityId);
    $msg = $nick . ',您好!' . $city . '明天' . $tomorrow['Weah'] . ',温度' . $tomorrow['Temp'] . ',关注天气变化,注意身体哦~' . $serviceIntro;
    $SMSUrl = $sendBaseUrl . '?phone=' . $mobileNo . '&pwd=' . $mobilePwd . '&to=' . $mobile .'&u=1&msg=' . $msg;
    $SMSResult = httpRequest($SMSUrl);
    if($SMSResult == '200'){
      //Change sent state.
      $xml -> formatOutput = true;
      // $user -> getElementsByTagName('today') -> item(0) -> nodeValue = 1;// 看到这一句和下一句了吗?
      $today = 1;
      $xml -> save('userfeed.xml');
    }
  }
}

喵了个咪的,看到中文注释那里了吗?为了排除问题,我把两个方式都用上了。最后确实可以发送出去短信,但是 xml 里的 today 值压根就没有变化。。我还尝试了 saveXML('userfeed.xml'); ,我还尝试了把保存的语句写在 foreach 循环的外面。。实际上这好像是个不可能的任务了。。

所以我想,应该只能用数据库了。

顺便说一句,在本地进行测试的时候,获取天气数据有很多时候都是返回空字符,没有仔细研究原因。而在服务器上则不会出现这种情况。