`

手把手教你在SAE上打造自己的免费天气预报应用

阅读更多

最近开始学习PHP语言,本着理论联系实际的原则,边学边做个小项目。也没什么好的想法,于是就继续做天气预报吧。没钱租空间,而Google App Engine使用起来在国内有些限制(比如需要“翻土啬”才能打开应用主页),所以暂时放弃。而新浪云(以下简称SAE)当前正火,使用门槛较低,实名认证后可以免费使用很长时间,就它了!

大家可以先看一下应用完成后的样子。网址http://zhitianqi.sinaapp.com,猛击此处进入

这是我刚刚做好的一个天气应用,这个应用有一个简单的主页,打开后根据IP地址显示当前所在城市的天气预报,包含当天天气详情以及常用的几个生活指数。在该页面还可以手动更换城市,以及订阅免费的天气预报短信。当然这里订阅的实际上是“邮件”,只不过使用手机邮箱(移动139邮箱,联通手机邮箱或者电信189邮箱)订阅的话,邮箱收到天气预报时,会给手机发送短信提醒,进而实现了短信天气预报。



 

OK,接一下咱一步一步实现这个天气应用。(SAE的注册与认证很简单,这里就不说了)

 

第一步:创建一个新的应用

点击页面最上边的“我的应用”,打开应用列表,这里会显示所有你创建的应用。



 再点击“创建新应用”,打开创建新应用页面。

 这里我们选择创建空应用,然后按要求填表。这里注意3个地方:二级域名也就是AppID,开发语言以及应用类型。二级域名不能重复,本来想用tianqi的,不过已经被人注册了,我就写tianqi123,这同时也是我们这个应用的应用ID。这个ID决定了将来应用主页网址就是http://tianqi123.sinaapp.com。开发语言选择PHP,应用类型选择Web应用。然后点击创建应用。

 这时候会弹出“安全认证”窗口,注意此处要的是安全密码而不是登录密码!

 经过安全验证后,一个SAE应用就创建成功了。接下来就要准备代码了。

 

第二步:安装TortoiseSVN并进行代码检出

TortoiseSVN下载地址:http://tortoisesvn.net/downloads.html,有两个版本,根据你的系统选择32位或64位版本,不要选错了。下载安装之后,点击右键发现多了TortoiseSVN的菜单。点击SVN Checkout,进行代码检出。注意每次修改代码前都要进行代码检出。

 

 


 
 点击确定后,等到提示Competed At revision: 0(以后每次检出成功这个数字都会加1)时,就完成了代码检出。此时在所选文件夹下(此处是E:\blog)就多了一个tianqi123的文件夹,这个文件夹图标上还有一个绿色的对号。



 进入这个文件夹,然后在里面新建一个文件夹,名称为数字1(SAE应用版本号只能是1~10的整数数字)。

 

第三步:开始编写代码吧

打开1文件夹,新建一个名为index.php的文件,这个文件就是应用主页。打开index.php文件,把以下代码复制进去,然后保存。

 

<?php
require_once('func.php');
require_once('get_guest_info.php');

$query_string = $_SERVER["QUERY_STRING"];
//处理POST请求
if ($_POST) {
    $w_info = get_weather_by_name($_POST['city']);
} elseif (preg_match('/^c=(\d{9})$/', $query_string, $matches)) {
    $city_code = $matches[1];
    $w_info    = get_weather_by_code($city_code);
} else {
    // 根据IP地址显示当地天气
    $gifo     = new get_guest_info();
    $address  = $gifo->Getaddress_2();
    $reg_addr = '/((.+)省|新疆|内蒙古|宁夏|广西|西藏)?(.*)市/';
    preg_match($reg_addr, $address['country'], $matches);
    $prov   = $matches[2] ? $matches[2] : $matches[1]; //得到省份名称
    $city   = $matches[3]; //得到城市名称
    $w_info = get_weather_by_name($city);
}

$title        = $w_info['city'] . '天气预报';
$cityid       = $w_info['cityid'];
$poster       = "http://poster.weather.com.cn/p_files/base/" . $cityid . ".jpg";
$date         = $w_info['date_y'];
$release_time = $date . $w_info['fchh'] . '时发布';
$tempreture   = array(
    $w_info['temp1'],
    $w_info['temp2'],
    $w_info['temp3'],
    $w_info['temp4'],
    $w_info['temp5']
);
$weather      = array(
    $w_info['weather1'],
    $w_info['weather2'],
    $w_info['weather3'],
    $w_info['weather4'],
    $w_info['weather5']
);
$wind         = array(
    $w_info['wind1'],
    $w_info['wind2'],
    $w_info['wind3'],
    $w_info['wind4'],
    $w_info['wind5']
);
$day_image    = array(
    $w_info['img1'],
    $w_info['img3'],
    $w_info['img5'],
    $w_info['img7'],
    $w_info['img9']
);
$night_image  = array(
    $w_info['img2'],
    $w_info['img4'],
    $w_info['img6'],
    $w_info['img8'],
    $w_info['img10']
);
for ($i = 0; $i < 5; $i++) {
    $day_image[$i]   = sprintf('%02s', $day_image[$i]);
    $night_image[$i] = sprintf('%02s', $night_image[$i]);
    if ($night_image[$i] == '99') {
        $night_image[$i] = $day_image[$i];
    }
}

$reg_date = '/(\d+)年(\d+)月(\d+)日/';
preg_match($reg_date, $date, $matches);
$today = mktime(0, 0, 0, $matches[2], $matches[3], $matches[1]);
$days  = array(
    $today,
    strtotime('+1 day', $today),
    strtotime('+2 day', $today),
    strtotime('+3 day', $today),
    strtotime('+4 day', $today)
);

$index_cy = $w_info['index_d']; //穿衣指数
$index_uv = $w_info['index_uv']; //紫外线指数
$index_cl = $w_info['index_cl']; //晨练指数
$index_ag = $w_info['index_ag']; //过敏指数
$index_xc = $w_info['index_xc']; //洗车指数
$index_tr = $w_info['index_tr']; //旅游指数
$index_co = $w_info['index_co']; //舒适度指数
$index_ls = $w_info['index_ls']; //晾晒指数
?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
    "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
      <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
  <title><?php
echo '我的天气预报 - ' . $title;
?></title>
</head>

<body>
<?php echo '<h1>' . $title . '</h1>'; ?>
<form method="post" action="">
      <input type="text" name="city" style="border: 1px solid #ccc;" size="13" />
      <input type="hidden" name="action" value="change_city" />
      <input type="submit" value="更换城市" class="button" />
</form>
<hr />
<h3>今日天气</h3>
<?php

printf('<img src="%s" alt="%s" /><br />', $poster, $city);
printf('今天是<b>%s</b>,<b>%s</b>,天气<b>%s</b>,气温<b>%s</b>,
	     <b>%s</b><br />', $date, get_week($today), $weather[0], $tempreture[0], $wind[0]);
echo '<b>紫外线指数:</b>' . $index_uv . '<br />';
echo '<b>舒适度指数:</b>' . $index_co . '<br />';
echo '<b>晨&nbsp;&nbsp;练指数:</b>' . $index_cl . '<br />';
echo '<b>晾&nbsp;&nbsp;晒指数:</b>' . $index_ls . '<br />';
echo '<b>过&nbsp;&nbsp;敏指数:</b>' . $index_ag . '<br />';
echo '<b>旅&nbsp;&nbsp;游指数:</b>' . $index_tr . '<br />';
echo '<b>穿&nbsp;&nbsp;衣指数:</b>' . $index_cy . '<br />';
?>


<hr />
    <h3>
    未来4日天气情况
    </h3>
    <!--表格-->
    <table class="weather">
      <tr>
	<?php
        $dd = array(
            '今天',
            '明天',
            '后天'
        );
        for ($i = 1; $i < 3; $i++) {
            echo '<th>';
            printf('%s(%s)', get_week($days[$i]), $dd[$i]);
            echo '</th>';
        }
        for (; $i < 5; $i++) {
            echo '<th>';
            printf('%s(%s)', get_week($days[$i]), date('j日', $days[$i]));
            echo '</th>';
        }
        ?>
	</tr>
	<tr>
	<?php
        for ($i = 1; $i < 5; $i++) {
            if ($i <> 4) {
                echo '<td>';
            } else {
                echo '<td style="border: 0;">';
            }
            printf('<img src="http://wap.weather.com.cn/m/i/icon_weather/21x15/d%s.gif" /><img src="http://wap.weather.com.cn/m/i/icon_weather/21x15/n%s.gif" /><br />', $day_image[$i], $night_image[$i]);
            printf('<b>%s</b><br />%s<br />%s', $tempreture[$i], $weather[$i], $wind[$i]);
            echo '</td>';
        }
        ?>
	</tr>
	</table>
<hr />
	  <h3>免费订阅天气预报</h3>
          <p>仅需3步,获得早晚短信天气预报,而且是<b>免费</b>的哟!</p>
            <ol>
                  <li>开通<b>免费的</b><a href="http://mail.10086.cn/" target="_blank">移动139邮箱</a>或者
                              <a href="http://mail.wo.com.cn/" target="_blank">联通手机邮箱</a>或者
                              <a href="http://mail.189.cn/" target="_blank">电信189邮箱</a>;
                  </li>
                  <li>设置邮件提醒方式为<b>长短信</b>;</li>
                  <li>留下您的邮箱和城市,天气预报将以短信方式发至您的手机,早晚各一次。</li>
            </ol>
            <!--Subscribe form-->
            <form method="post" id="customForm" action="result.php">
                  <table>
                        <tr>
                              <th><label for="email">邮箱</label></th>
                              <td><input id="email" name="email" type="text" /></td>
                              <td><span id="emailInfo">请留下您的邮箱地址吧!</span></td>
                        </tr>
                        <tr>
                              <th><label for="city">城市</label></th>
                              <td><input id="city" name="city" type="text" /></td>
                              <td><span id="cityInfo">您想关注哪个城市的天气?</span></td>
                        </tr>
                        <tr>
                              <th>&nbsp;</th>
                              <td><div class="QapTcha"></div></td>
                        </tr>
                        <tr>
                              <th>&nbsp;</th>
                              <td><input type="submit" name="sub" value="订阅" class="button" /></td>
                        </tr>
                        <input type="hidden" name="action" value="subscribe" />			      
                  </table>
          </form>
<hr />  
<h3>友情链接</h3>
<script type="text/javascript"><!--
google_ad_client = "ca-pub-8820899098050798";
/* 大尺寸横版 链接单元 728 x 15 */
google_ad_slot = "4864840936";
google_ad_width = 728;
google_ad_height = 15;
//-->
</script>
<script type="text/javascript"
src="http://pagead2.googlesyndication.com/pagead/show_ads.js">
</script>
<a href="http://think3t.iteye.com" style="margin-left: 10px;font-size: 14px;line-height: 16px;">►&nbsp;三思之旅</a>
<a href="http://zhitianqi.sinaapp.com" style="margin-left: 30px;font-size: 14px;line-height: 16px;">►&nbsp;知天气</a>
<hr />
<h3>站内统计</h3>
<?php
$counter = new SaeCounter();
$counter->create('guest', 0);
if ($counter->exists('guest')) {
    $counter->incr('guest');
} else {
    $counter->create('guest', 0);
    $counter->incr('guest');
}
$guest_num = $counter->get('guest');
echo '<div style="margin-left: 4px;">';
printf('当前有<b style="color: red;">&nbsp;%s&nbsp;</b>位用户访问本站<br />', $guest_num);
printf('其中有<b style="color: red;">&nbsp;%s&nbsp;</b>位用户订阅天气', get_user_num());
echo '</div>';
?>
<div id="footer">2013 Powered by <a href="http://think3t.iteye.com/">三思之旅</a></div>
</body>
</html>

 接下来再新建一个名为func.php的文件,复制以下内容并保存。这个文件是获取天气信息、获取城市代码等函数的代码。

<?php
require_once('db-config.php');

function get_city_code($city_name = '北京')
{
    $remote_server = 'http://search.weather.com.cn/wap/search.php';
    $post_data     = array(
        'city' => $city_name,
        'submit' => 'submit'
    );
    
    $ch = curl_init();
    curl_setopt($ch, CURLOPT_URL, $remote_server);
    curl_setopt($ch, CURLOPT_POST, true);
    curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($post_data));
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
    $data = curl_exec($ch);
    curl_close($ch);
    //Post的返回结果如下:
    //<script>window.location="http://wap.weather.com.cn/wap/weather/101010100.shtml";</script>
    $data = explode("/", $data); //$data[5]='101010100.shtml";<';
    $data = explode('.', $data[5]);
    return $data[0];
}

function get_weather_by_name($city_name = '北京')
{
    $city_code    = get_city_code($city_name);
    $weatherurl   = "http://m.weather.com.cn/data/" . $city_code . ".html";
    $weatherjson  = file_get_contents($weatherurl);
    $weatherarray = json_decode($weatherjson, true);
    $weatherinfo  = $weatherarray['weatherinfo'];
    return $weatherinfo;
}

function get_weather_by_code($city_code = '101010100')
{
    $weatherurl   = "http://m.weather.com.cn/data/" . $city_code . ".html";
    $weatherjson  = file_get_contents($weatherurl);
    $weatherarray = json_decode($weatherjson, true);
    $weatherinfo  = $weatherarray['weatherinfo'];
    return $weatherinfo;
}

function get_weather_sms_by_code($city_code = '101010100')
{
    $w_info     = get_weather_by_code($city_code);
    $title      = $w_info['city'] . '天气';
    $date       = $w_info['date_y'];
    $tempreture = array(
        $w_info['temp1'],
        $w_info['temp2'],
        $w_info['temp3']
    );
    $weather    = array(
        $w_info['weather1'],
        $w_info['weather2'],
        $w_info['weather3']
    );
    $wind       = array(
        $w_info['wind1'],
        $w_info['wind2'],
        $w_info['wind3']
    );
    
    $reg_date = '/(\d+)年(\d+)月(\d+)日/';
    preg_match($reg_date, $date, $matches);
    $today = mktime(0, 0, 0, $matches[2], $matches[3], $matches[1]);
    $days  = array(
        $today,
        strtotime('+1 day', $today),
        strtotime('+2 day', $today),
        strtotime('+3 day', $today)
    );
    for ($i = 0; $i < 3; $i++) {
        $days_string[$i] = date('j日', $days[$i]) . '[' . get_week($days[$i], true) . ']';
    }
    $weather_sms = array(
        $title,
        $days_string,
        $weather,
        $tempreture,
        $wind
    );
    return $weather_sms;
}

function get_week($day, $short = false)
{
    $week_short = array(
        '周日',
        '周一',
        '周二',
        '周三',
        '周四',
        '周五',
        '周六'
    );
    $week       = array(
        '星期日',
        '星期一',
        '星期二',
        '星期三',
        '星期四',
        '星期五',
        '星期六'
    );
    $w          = date('w', $day);
    if ($short)
        return $week_short[$w];
    else
        return $week[$w];
}

function init_db()
{
    $conn = @mysql_connect(DB_HOST_M, DB_USER, DB_PASSWORD) or die('数据库连接失败:' . mysql_error());
    
    if ($conn) {
        //选择数据库
        mysql_select_db(DB_NAME, $conn);
        $sql = 'CREATE TABLE subscriber
			(
			ID int NOT NULL AUTO_INCREMENT,
			PRIMARY KEY(ID),
			Mail varchar(30),
			CityName varchar(20),
			CityCode varchar(9)
			)';
        mysql_query($sql, $conn);
    }
    mysql_close($conn);
}

function add_user($mail, $city_name)
{
    $city_code = get_city_code($city_name);
    $conn = @mysql_connect(DB_HOST_M, DB_USER, DB_PASSWORD) or die('数据库连接失败:' . mysql_error());
    if ($conn) {
        mysql_select_db(DB_NAME, $conn);
        $sql = "INSERT INTO subscriber (Mail, CityName, CityCode) VALUES ('$mail', '$city_name', '$city_code')";
        //$sql = "INSERT INTO subscriber (Mail, CityName, CityCode) VALUES ('test@test.com', '宜阳', '123456789')";
        @mysql_query($sql, $conn) or die('数据库插入失败:' . mysql_error());
    }
    mysql_close($conn);
}

function get_user_num()
{
    $conn = @mysql_connect(DB_HOST_M, DB_USER, DB_PASSWORD) or die('数据库连接失败:' . mysql_error());
    if ($conn) {
        mysql_select_db(DB_NAME, $conn);
        $sql = "SELECT * FROM subscriber";
        $result = @mysql_query($sql, $conn) or die(mysql_error());
        mysql_close($conn);
        return mysql_numrows($result);
    }
}

function send_weather()
{
    $conn = @mysql_connect(DB_HOST_M, DB_USER, DB_PASSWORD) or die('数据库连接失败:' . mysql_error());
    if ($conn) {
        mysql_select_db(DB_NAME, $conn);
        $sql = "SELECT Mail, CityCode FROM subscriber";
        $result = @mysql_query($sql, $conn) or die(mysql_error());
        $city_list = array();
        while ($row = mysql_fetch_assoc($result)) {
            $city_list[$row['CityCode']] .= $row['Mail'] . ',';
        }
        $mail = new SaeMail();
        foreach ($city_list as $city => $mails) {
            $w_info = get_weather_sms_by_code($city);
            $to     = trim($mails, ',');
            $sub    = $w_info[0];
            $msg    = '';
            for ($i = 0; $i < 3; $i++) {
                $msg .= sprintf('%s:%s,%s,%s。%s', $w_info[1][$i], $w_info[2][$i], $w_info[3][$i], $w_info[4][$i], PHP_EOL);
            }
            printf('<b>%s</b>: %s<br /><hr>', $city, $to);
            printf('%s<br />%s', $sub, $msg);
            $options = array(
                'from' => 'think3t@126.com',
                'to' => $to,
                'smtp_host' => 'smtp.126.com',          //SMTP服务器
                'smtp_port' => '25',                    //SMTP服务器端口
                'smtp_username' => 'yourname@126.com',   //邮箱帐号
                'smtp_password' => 'password',           //邮箱密码
                'subject' => $sub,
                'content' => $msg,
                'content_type' => 'TEXT',
                'charset' => 'utf8',
                'tls' => false
            );
            $mail->setOpt($options);
            $ret = $mail->send();
            //发送失败时输出错误码和错误信息
            if ($ret === false)
                var_dump($mail->errno(), $mail->errmsg());
            else
                echo $sub . '发送完毕!' . '<br />';
            echo '<hr><hr>';
        }
        mysql_close($conn);
    }
}

?>

 这个地方需要做一点小的改动,就是把你自己的邮箱信息写上去。建议专门申请一个邮箱用来发送天气信息。下面说一下改哪里。

在func.php文件中,找到以下几行,根据注释改成你自己的邮箱即可。

'smtp_host' => 'smtp.126.com',          //SMTP服务器
'smtp_port' => '25',                    //SMTP服务器端口
'smtp_username' => 'yourname@126.com',   //邮箱帐号
'smtp_password' => 'password',           //邮箱密码

 再新建一个名为get_guest_info.php的文件,复制以下代码并保存。这个文件实现了通过IP确定地理位置的功能。

<?php
/* 作用取得客户端的ip、地理信息、浏览器http://blog.qita.in
 * 使用方法如下
 
 $gifo = new get_guest_info();
 $addr = $gifo->Getaddress_1();
 echo $addr['country'].'<br />'.$addr['local'];
 echo toUTF8("<br/>浏览器类型:").$gifo->GetBrowser();
 echo toUTF8("<br/>浏览器语言:").toUTF8($gifo->GetLang());
 echo toUTF8("<br/>操作系统:").$gifo->GetOs(); 
 
 */
require_once('phpcharset.php'); //字符编码格式转换
class get_guest_info
{
    ////获得访客浏览器类型
    function GetBrowser()
    {
        if (!empty($_SERVER['HTTP_USER_AGENT'])) {
            $br = $_SERVER['HTTP_USER_AGENT'];
            if (preg_match('/MSIE/i', $br)) {
                $br = 'MSIE';
            } elseif (preg_match('/Firefox/i', $br)) {
                $br = 'Firefox';
            } elseif (preg_match('/Chrome/i', $br)) {
                $br = 'Chrome';
            } elseif (preg_match('/Safari/i', $br)) {
                $br = 'Safari';
            } elseif (preg_match('/Opera/i', $br)) {
                $br = 'Opera';
            } else {
                $br = 'Other';
            }
            return $br;
        } else {
            return "获取浏览器信息失败!";
        }
    }
    
    ////获得访客浏览器语言
    function GetLang()
    {
        if (!empty($_SERVER['HTTP_ACCEPT_LANGUAGE'])) {
            $lang = $_SERVER['HTTP_ACCEPT_LANGUAGE'];
            $lang = substr($lang, 0, 5);
            if (preg_match("/zh-cn/i", $lang)) {
                $lang = "简体中文";
            } elseif (preg_match("/zh/i", $lang)) {
                $lang = "繁体中文";
            } else {
                $lang = "English";
            }
            return $lang;
            
        } else {
            return "获取浏览器语言失败!";
        }
    }
    
    ////获取访客操作系统
    function GetOs()
    {
        if (!empty($_SERVER['HTTP_USER_AGENT'])) {
            $OS = $_SERVER['HTTP_USER_AGENT'];
            if (preg_match('/win/i', $OS)) {
                $OS = 'Windows';
            } elseif (preg_match('/mac/i', $OS)) {
                $OS = 'MAC';
            } elseif (preg_match('/linux/i', $OS)) {
                $OS = 'Linux';
            } elseif (preg_match('/unix/i', $OS)) {
                $OS = 'Unix';
            } elseif (preg_match('/bsd/i', $OS)) {
                $OS = 'BSD';
            } else {
                $OS = 'Other';
            }
            return $OS;
        } else {
            return "获取访客操作系统信息失败!";
        }
    }
    
    ////获得访客真实ip
    function Getip()
    {
        if (!empty($_SERVER["HTTP_CLIENT_IP"])) {
            $ip = $_SERVER["HTTP_CLIENT_IP"];
        }
        if (!empty($_SERVER['HTTP_X_FORWARDED_FOR'])) { //获取代理ip
            $ips = explode(',', $_SERVER['HTTP_X_FORWARDED_FOR']);
        }
        if ($ip) {
            $ips = array_unshift($ips, $ip);
        }
        
        $count = count($ips);
        for ($i = 0; $i < $count; $i++) {
            if (!preg_match("/^(10|172\.16|192\.168)\./i", $ips[$i])) { //排除局域网ip
                $ip = $ips[$i];
                break;
            }
        }
        $tip = empty($_SERVER['REMOTE_ADDR']) ? $ip : $_SERVER['REMOTE_ADDR'];
        if ($tip == "127.0.0.1") { //获得本地真实IP
            return $this->get_onlineip();
        } else {
            return $tip;
        }
    }
    
    ////获得本地真实IP
    function get_onlineip()
    {
        $mip = file_get_contents("http://iframe.ip138.com/ic.asp");
        if ($mip) {
            preg_match("/\[.*\]/", $mip, $sip);
            $p = array(
                "/\[/",
                "/\]/"
            );
            return preg_replace($p, "", $sip[0]);
        } else {
            return toUTF8("获取本地IP失败!");
        }
    }
    
    ////根据ip获得访客所在地地名:基于纯真数据库
    function Getaddress_1($ip = '')
    {
        if (empty($ip)) {
            $ip = $this->Getip();
        }
        
        require('qqwrt_parser.php');
        $QQWry              = new QQWry;
        $ifErr              = $QQWry->QQWry($ip);
        $address            = array();
        $address['country'] = toUTF8($QQWry->Country);
        $address['local']   = toUTF8($QQWry->Local);
        return $address;
    }
    
    ////根据ip获得访客所在地地名:从ip138获取
    function Getaddress_2($ip = '')
    {
        //来自:XX省XX市 电信
        if (empty($ip)) {
            $ip = $this->Getip();
        }
        $get_url = sprintf('http://wap.ip138.com/ip_search.asp?ip=%s', $ip);
        $mip     = file_get_contents($get_url);
        if ($mip) {
            preg_match("/查询结果:(\S+)\s+(\S+)/", $mip, $sip);
            $address            = array();
            $address['country'] = toUTF8($sip[1]);
            $address['local']   = toUTF8($sip[2]);
            return $address;
        } else {
            return toUTF8("获取本地IP失败!");
        }
    }
}

?>

 再新建一个phpcharset.php文件,复制以下代码并保存。这个文件实现了字符串编码方式的转换,我这里主要是把其他编码格式转换成UTF8,以免引起中文乱码。

<?php
function phpcharset($data, $to)
{
    if (is_array($data)) {
        foreach ($data as $key => $val) {
            $data[$key] = phpcharset($val, $to);
        }
    } else {
        $encode_array = array(
            'ASCII',
            'UTF-8',
            'GBK',
            'GB2312',
            'BIG5'
        );
        $encoded      = mb_detect_encoding($data, $encode_array);
        $to           = strtoupper($to);
        if ($encoded != $to) {
            $data = mb_convert_encoding($data, $to, $encoded);
        }
    }
    return $data;
}

function toUTF8($data)
{
    return phpcharset($data, 'UTF-8');
}

function toGBK($data)
{
    return phpcharset($data, 'GBK');
}

function toASCII($data)
{
    return phpcharset($data, 'ASCII');
}

function toGB2312($data)
{
    return phpcharset($data, 'GB2312');
}

function toBIG5($data)
{
    return phpcharset($data, 'BIG5');
}
?>

 然后继续新建一个php文件,名称为validation.php,用来实现对邮箱、城市名称等的校验,保证只有输入合法的邮箱地址和正确的城市名称才能订阅天气。代码如下。

<?php
function validateCity($city)
{
    //if it's NOT valid
    if (strlen($city) < 1)
        return false;
    //if it's valid
    else
        return true;
}
function validateEmail($email)
{
    return preg_match("/^[a-zA-Z0-9]+[a-zA-Z0-9_.-]+[a-zA-Z0-9_-]+@[a-zA-Z0-9]+\.[a-zA-Z0-9]+(\.[a-zA-Z0-9]+)*$/", $email);
}
function isCityFound($city)
{
    if (($_POST['city'] <> '北京') && (get_city_code($_POST['city']) == '101010100'))
        return false;
    else
        return true;
}
?>

 还需要再新建一个名为db-config.php文件,保存MySQL数据库的信息。代码很简单,如下所示:

<?php
/** The name of the database for SAE */
define('DB_NAME', SAE_MYSQL_DB);

/** MySQL database username */
define('DB_USER', SAE_MYSQL_USER);

/** MySQL database password */
define('DB_PASSWORD', SAE_MYSQL_PASS);

/** MySQL Master hostname */
define('DB_HOST_M', SAE_MYSQL_HOST_M . ':' . SAE_MYSQL_PORT);

/** MySQL Slaver hostname */
define('DB_HOST_S', SAE_MYSQL_HOST_S . ':' . SAE_MYSQL_PORT);
?>

 最后还有一个php文件,名字叫做result.php。这个页面是提交订阅信息后的结果页面,根据你输入的信息,显示订阅成功,或者在订阅失败时给出提示。代码如下

<?php
require_once('func.php');
require_once('validation.php');
?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
    "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
      <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
  <title><?php echo '知天气 - ' . $title; ?></title>
</head>

<body>
<?php
$post_city = trim($_POST['city']);
$post_mail = trim($_POST['email']);
if (isset($_POST['sub']) && (!validateCity($post_city) || !validateEmail($_POST['email']) || !isCityFound($post_city))) {
    echo '<h1>订阅失败</h1>';
    echo '<div id="error">';
    echo '<ul>';
    if (!validateEmail($post_mail))
        echo '<li><strong>邮箱错误:</strong>请输入您正确的邮箱地址!</li>';
    if (!validateCity($post_city))
        echo '<li><strong>城市错误:</strong>请输入您关注的城市名称!</li>';
    elseif (!isCityFound($post_city))
        echo '<li><strong>城市错误:</strong>未找到您要关注的城市,请重新输入。</li>';
    echo '</ul>';
    echo '</div>';
} elseif (isset($_POST['sub'])) {
    add_user($post_mail, $post_city);
    echo '<h1>订阅成功</h1>';
    echo '<div id="error" class="valid">';
    echo '<ul>';
    printf('<li>您已成功订阅<a href="index.php?c=%s">%s天气预报</a>,感谢您的关注~</li>', get_city_code($post_city), $post_city);
    echo '</ul>';
    echo '</div>';
}
?>
<a href="index.php">返回首页</a>
</body>
</html>

 现在差定时发送天气预报的php页面。再新建一个php文件,命名为send_weather.php。访问这个页面就会给所有订阅的天气预报的用户发送天气信息,我们的目标是实现定时自动发送,所以这个页面平时不需要访问,为了以示区别,专门给它建立一个文件夹,名字叫做cron,然后把send_weather.php文件放进cron文件夹。send_weather.php的代码如下所示:

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<html>
<head>
	<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
	<title>发送天气短信</title>
</head>

<body>
<?php
require_once('../func.php');
send_weather();
?>
</body>
</html>

 为了实现定时发送天气预报,还需要加入定时信息。新建一个config.yaml文件,这个文件就是SAE应用的配置文件,这个文件要放在项目根目录下,也就是和index.php放在一起。然后打开config.yaml文件,把以下内容复制进去并保存。注意name和version那里填写你自己的SAE应用ID(也就是二级域名)和相应的版本号。这里边包含两条定时信息,分别是早上8点15和晚上18点15各发一次天气信息,应用路径其实都是send_weather.php,但是SAE的多个cron的url不能完全相同,如果多个cron中使用了相同的url,后面的cron会覆盖前面的cron。所以18点15那一条定时信息的URL路径中添加无用的参数"?cron=1"以避免覆盖。

name: tianqi123
version: 1

cron:
    - description: 每天早上8点15发送天气预报
    url: cron/send_weather.php
    schedule: every day of month 08:15
    - description: 每天晚上6点15发送天气预报
    url: cron/send_weather.php?cron=1
    schedule: every day of month 18:15

 好了,到现在为止,所有的代码工作都完成了,那就上传到服务器吧。不过上传之前还是再确认一下有没有多或者少文件,以及文件路径是否正确。对比一下我的tianqi123文件夹结构,看看你的项目是这样的吗?


 确认无误后就可以上传代码了,这一步还要使用SVN。

 

第四步:上传代码

在tianqi123这个文件夹下的空白处点南鼠标右键,选择TortoiseSVN——>Add,打开Add对话框。


 在Add对话框中,确认所有的文件夹和文件都已经被选中,然后点击OK。


 稍等片刻,当出现以下窗口时,增加文件就完成了。


 点击OK关掉这个对话框,然后可以发现刚才选中的文件夹和文件的图标上都有一个加号,而tianqi123这个文件夹图标上多了一个红色的感叹号。然后在tianqi123文件夹上点右键并选择SVN Commit,进行代码提交。

 

点击SVN Commit之后会打开下边的对话框,确定所有代码都已经选择上,并且在Message框中写上本次代码提交的原因。注意Message一栏不能为空,不然无法提交代码。

 

 单击“OK”开始同步,如果是第一次使用会弹出Authentication窗口进行身份验证,

  • username:注册SAE时填写的 安全邮箱(并非微博帐号)
  • password:注册SAE时填写的 安全密码(并非微博密码)

另外,如果您不希望每次使用都进行身份验证,可以勾选Save authentication复选框。


 输入正确的帐号密码之后点击OK,就开始上传代码了。等到出现Complete At revision: 1(这个数字是Checkout时看到的那个数字加1)时,代码就上传成功了。是不是有点迫不及待想看看咱们的成果了呢?别急,还有最后一步。

 

第五步:初始化MySQL

因为我们用到了MySQL,而SAE应用默认情况下是没有启用MySQL服务的,所以我们还需要对MySQL进行初始化并进行简单的设置。

登录进去自己的SAE帐号,然后进入“我的应用”,在我创建的应用中,点击我们之前创建的那个应用,我这里就是“我的天气预报”。


 然后就进入了“我的天气预报”的应用信息页面。点击左侧的服务管理中的MySQL,打开MySQL服务管理。


 然后点击“点此初始化MySQL”按钮。然后会弹出安全认证对话框,输入安全密码(非微博密码)后点击安全验证按钮。


 等待片刻,弹出初始化成功对话框时,说明MySQL已经初始化完成了。


 关掉对话框,回到MySQL服务管理页面。然后单击“管理MySQL”按钮,打开PHPMyAdmin页面。


 在这个页面中我们可以看到,在这个应用的数据库中还没有表,所以我们需要新建一个数据表了。直接用SQL代码进行操作吧,点击上图椭圆框中的SQL按钮,然后输入以下SQL代码,并点击执行,数据表就创建成功了。


 SQL代码如下:

create table `subscriber`( 
   `ID` int NOT NULL AUTO_INCREMENT , 
   `Mail` varchar(40) NOT NULL , 
   `CityName` varchar(16) NOT NULL , 
   `CityCode` varchar(9) NOT NULL , 
   PRIMARY KEY (`ID`)
 )
 

 

到此为止,所有的工作都已经完成了。打开浏览器,输入应用地址,我的应用地址就是http://tianqi123.sinaapp.com,终于看到成果了!!

 

 

结束语:

本文基本上是手把手地教大家创建了一个SAE天气应用。这个天气应用很简单,但是却可以给你的手机订阅一个免费的天气预报短信。当然,或许大家的手机上已经有天气预报的软件了,觉得这个天气短信有点多余了,其实不然,至少这个天气短信不需要任何流量。而且,也并不是所有人都在使用智能手机,你可以给你的父母、亲朋好友,给那些不会使用智能手机的人送上一份免费的天气预报。

本人也是PHP初学者,对HTML、CSS也是一知半解,所以本文只讨论了PHP的实现,并未涉及CSS的设计。因此,完成后的应用主页稍显简陋,大家将就看吧。

如果你看了本文,觉得自己动手新建一个SAE应用比较麻烦的话,可以访问我的“知天气”应用,同样也可以免费订阅天气哦~

知天气网址http://zhitianqi.sinaapp.com/

END

 

本人由三思之旅原创,转载请注明出处!

  • 描述: 知天气
  • 大小: 123.2 KB
  • 描述: 页面最上边的“我的应用”
  • 大小: 7.8 KB
  • 描述: 创建新应用
  • 大小: 10.2 KB
  • 描述: 创建一个空应用
  • 大小: 37.7 KB
  • 描述: 安全认证
  • 大小: 7 KB
  • 描述: SVN菜单
  • 大小: 15.3 KB
  • 描述: 代码检出
  • 大小: 46.2 KB
  • 描述: 代码检出完成
  • 大小: 83.6 KB
  • 描述: 项目文件夹
  • 大小: 25 KB
  • 描述: 项目结构
  • 大小: 2.5 KB
  • 描述: 添加项目文件到SVN库
  • 大小: 47.7 KB
  • 描述: Add对话框
  • 大小: 32.9 KB
  • 描述: 增加文件完成
  • 大小: 53.9 KB
  • 描述: SVN Commit...
  • 大小: 13.6 KB
  • 描述: Commit对话框
  • 大小: 65.4 KB
  • 描述: Authentication对话框
  • 大小: 7.5 KB
  • 描述: 代码上传完成
  • 大小: 64.8 KB
  • 描述: 我创建的应用
  • 大小: 24.5 KB
  • 描述: 服务管理--MySQL
  • 大小: 6 KB
  • 描述: MySQL服务管理
  • 大小: 8.5 KB
  • 描述: MySQL服务初始化成功
  • 大小: 1.4 KB
  • 描述: 点击管理MySQL按钮
  • 大小: 15.7 KB
  • 描述: PHPMyAdmin页面
  • 大小: 11.3 KB
  • 描述: 新建表的SQL代码
  • 大小: 15.3 KB
  • 描述: 成功创建了一个数据表
  • 大小: 20.4 KB
分享到:
评论
1 楼 gougou139 2013-09-17  
我按你说的做了,但是乱码了

能指导一下吗

相关推荐

    手把手教你学DSP:基于TMS320F28335

    手把手教你学DSP:基于TMS320F28335 手把手教你学DSP:基于TMS320F28335 手把手教你学DSP:基于TMS320F28335 手把手教你学DSP:基于TMS320F28335 手把手教你学DSP:基于TMS320F28335 手把手教你学DSP:基于TMS320F...

    手把手教你学dsp2812,手把手教你学dsp2812pdf下载,C,C++

    《手把手教你学DSP2812》是一本专为初学者设计的 DSP(Digital Signal Processor)学习指南,主要围绕TI公司的TMS320F2812 DSP芯片进行讲解。这本书以其全面且易懂的特性,为读者提供了一个深入理解数字信号处理及其...

    手把手教你学DSPPDF

    【标题】"手把手教你学DSPPDF"是一份针对数字信号处理(DSP)初学者的教程性PDF文档,旨在引领读者逐步掌握这一领域的基础知识。该文档可能包含了从理论概念到实际应用的全面讲解,适合那些希望踏入数字信号处理世界...

    手把手教你写天气预报

    手把手教你写天气预报,这个程序虽小,但是基本的东西都是具有的。另外,此文档由于做得倡促,在博客随便粘过来的。没有好好排版,如果看得不爽请到博客里看原文。

    手把手教你学DSP—基于TMS320F28335的应用开发及实战配套程序.zip

    《手把手教你学DSP—基于TMS320F28335的应用开发及实战配套程序》这个压缩包文件,主要围绕着数字信号处理器(DSP)的应用开发展开,特别是针对Texas Instruments(TI)的TMS320F28335型号。TMS320F28335是一款高...

    手把手教你学28335

    手把手教你学28335PDF文档,看了这个确实和2812有了对比

    《手把手教你学51单片机》教材pdf

    《手把手教你学51单片机》是一本专为初学者设计的嵌入式开发入门教程,旨在帮助读者从零开始掌握51单片机的基础知识和应用技能。51单片机是嵌入式系统中最基础且广泛应用的一类微控制器,广泛应用于智能家居、工业...

    手把手教你dsp28335,高清pdf

    手把手教你学DSP28335高清pdf文件,北京航空航天大学出版社

    手把手教你学DSP28335

    手把手教你学DSP28335,PDF格式,有助于随时随地可以学习知识。

    手把手教你学51单片机C语言版PDF

    《手把手教你学51单片机C语言版》是一本专为初学者设计的教程,旨在帮助读者从零开始掌握51系列单片机的编程与应用。这本书由权威的电子技术教育平台www.kingst.org提供,是学习单片机C语言编程的宝贵资源。下面将...

    手把手教你学DSP—基于TMS320F28335的应用开发及实战1-5章课件.zip

    《手把手教你学DSP—基于TMS320F28335的应用开发及实战》是一本深入浅出的教程,主要针对Texas Instruments(TI)的TMS320F28335数字信号处理器(DSP)进行讲解。这门课程涵盖的内容丰富,从基础到实践,为读者提供...

    《手把手教你学dsp2812》顾卫刚.PDF

    根据给出的文件信息,《手把手教你学dsp2812》是顾卫刚所著的一本关于DSP2812的教材书籍。DSP2812指的是德州仪器(Texas Instruments,简称TI)的TMS320F2812数字信号处理器。TMS320F2812是一款32位的高性能数字信号...

    手把手教你学dsp

    手把手教你学dsp F2812 顾伟刚

    手把手教你打造apk安装器

    【标题】"手把手教你打造apk安装器"的教程涵盖了创建和使用自定义APK安装程序的核心技术。在Android平台上,APK是应用程序的二进制格式,通常通过Google Play或其他应用商店进行分发。然而,有时候我们可能需要创建...

    手把手教你构建自己的LINUX系统.part2.rar

    《手把手教你构建自己的Linux系统》以如何使用源代码搭建一套Linux系统这一独特的角度介绍Linux系统的构成,主要内容包括走进GNU/Linux、LFS,Linux系统定制原理,制作GNU/Linux系统的准备工作,本地定制GNU/Linux...

    手把手教你构建自己的LINUX系统.part1.rar

    《手把手教你构建自己的Linux系统》以如何使用源代码搭建一套Linux系统这一独特的角度介绍Linux系统的构成,主要内容包括走进GNU/Linux、LFS,Linux系统定制原理,制作GNU/Linux系统的准备工作,本地定制GNU/Linux...

    手把手教你构建自己的LINUX系统 三部分下载地址

    《手把手教你构建自己的Linux系统》以如何使用源代码搭建一套Linux系统这一独特的角度介绍Linux系统的构成,主要内容包括走进GNU/Linux、LFS,Linux系统定制原理,制作GNU/Linux系统的准备工作,本地定制GNU/Linux...

    手把手教你DSP配套资料

    “手把手教你DSP配套资料”这一压缩包很可能是包含了一系列关于DSP的学习材料,可能包括教程文档、示例代码、实验指导等。通过这些资料,你可以深入理解DSP的基本原理、算法和应用,逐步掌握实际操作技能,为你的...

    手把手教你整理自己的SQLServer日志

    教程名称:手把手教你整理自己的SQL Server日志课程目录:【】MSSQL数据库日志满的快速解决办法【】SQL2008删除过期备份【】sqlserver数据库事务日志备份与恢复原理【】SQL_server日志清除法【】利用日志传送实现高...

    手把手教你学51单片机-资源

    在《手把手教你学51单片机》中,宋雪松先生会讲解C语言的基本语法、变量类型、运算符、流程控制语句以及函数等概念,并结合51单片机的特性,教授如何编写能在单片机上运行的C程序。 接下来,我们将深入到单片机的...

Global site tag (gtag.js) - Google Analytics