欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

手把手教你在SAE上打造自己的免费天气预报应用 博客分类: 天气预报PHP编程 天气PHPSAE新浪云 

程序员文章站 2024-03-20 19:29:40
...

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

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

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


手把手教你在SAE上打造自己的免费天气预报应用
            
    
    博客分类: 天气预报PHP编程 天气PHPSAE新浪云 
 

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

 

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

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


手把手教你在SAE上打造自己的免费天气预报应用
            
    
    博客分类: 天气预报PHP编程 天气PHPSAE新浪云 
 再点击“创建新应用”,打开创建新应用页面。
手把手教你在SAE上打造自己的免费天气预报应用
            
    
    博客分类: 天气预报PHP编程 天气PHPSAE新浪云 
 这里我们选择创建空应用,然后按要求填表。这里注意3个地方:二级域名也就是AppID,开发语言以及应用类型。二级域名不能重复,本来想用tianqi的,不过已经被人注册了,我就写tianqi123,这同时也是我们这个应用的应用ID。这个ID决定了将来应用主页网址就是http://tianqi123.sinaapp.com。开发语言选择PHP,应用类型选择Web应用。然后点击创建应用。
手把手教你在SAE上打造自己的免费天气预报应用
            
    
    博客分类: 天气预报PHP编程 天气PHPSAE新浪云 
 这时候会弹出“安全认证”窗口,注意此处要的是安全密码而不是登录密码!
手把手教你在SAE上打造自己的免费天气预报应用
            
    
    博客分类: 天气预报PHP编程 天气PHPSAE新浪云 
 经过安全验证后,一个SAE应用就创建成功了。接下来就要准备代码了。

 

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

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

手把手教你在SAE上打造自己的免费天气预报应用
            
    
    博客分类: 天气预报PHP编程 天气PHPSAE新浪云 

 

手把手教你在SAE上打造自己的免费天气预报应用
            
    
    博客分类: 天气预报PHP编程 天气PHPSAE新浪云 

 

手把手教你在SAE上打造自己的免费天气预报应用
            
    
    博客分类: 天气预报PHP编程 天气PHPSAE新浪云 
 
 点击确定后,等到提示Competed At revision: 0(以后每次检出成功这个数字都会加1)时,就完成了代码检出。此时在所选文件夹下(此处是E:\blog)就多了一个tianqi123的文件夹,这个文件夹图标上还有一个绿色的对号。


手把手教你在SAE上打造自己的免费天气预报应用
            
    
    博客分类: 天气预报PHP编程 天气PHPSAE新浪云 


 进入这个文件夹,然后在里面新建一个文件夹,名称为数字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文件夹结构,看看你的项目是这样的吗?

手把手教你在SAE上打造自己的免费天气预报应用
            
    
    博客分类: 天气预报PHP编程 天气PHPSAE新浪云 
 确认无误后就可以上传代码了,这一步还要使用SVN。

 

第四步:上传代码

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

手把手教你在SAE上打造自己的免费天气预报应用
            
    
    博客分类: 天气预报PHP编程 天气PHPSAE新浪云 


 在Add对话框中,确认所有的文件夹和文件都已经被选中,然后点击OK。
手把手教你在SAE上打造自己的免费天气预报应用
            
    
    博客分类: 天气预报PHP编程 天气PHPSAE新浪云 


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

手把手教你在SAE上打造自己的免费天气预报应用
            
    
    博客分类: 天气预报PHP编程 天气PHPSAE新浪云 


 点击OK关掉这个对话框,然后可以发现刚才选中的文件夹和文件的图标上都有一个加号,而tianqi123这个文件夹图标上多了一个红色的感叹号。然后在tianqi123文件夹上点右键并选择SVN Commit,进行代码提交。
手把手教你在SAE上打造自己的免费天气预报应用
            
    
    博客分类: 天气预报PHP编程 天气PHPSAE新浪云 
 

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

手把手教你在SAE上打造自己的免费天气预报应用
            
    
    博客分类: 天气预报PHP编程 天气PHPSAE新浪云 

 

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

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

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

手把手教你在SAE上打造自己的免费天气预报应用
            
    
    博客分类: 天气预报PHP编程 天气PHPSAE新浪云 


 输入正确的帐号密码之后点击OK,就开始上传代码了。等到出现Complete At revision: 1(这个数字是Checkout时看到的那个数字加1)时,代码就上传成功了。是不是有点迫不及待想看看咱们的成果了呢?别急,还有最后一步。
手把手教你在SAE上打造自己的免费天气预报应用
            
    
    博客分类: 天气预报PHP编程 天气PHPSAE新浪云 
 

第五步:初始化MySQL

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

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

手把手教你在SAE上打造自己的免费天气预报应用
            
    
    博客分类: 天气预报PHP编程 天气PHPSAE新浪云 


 然后就进入了“我的天气预报”的应用信息页面。点击左侧的服务管理中的MySQL,打开MySQL服务管理。
手把手教你在SAE上打造自己的免费天气预报应用
            
    
    博客分类: 天气预报PHP编程 天气PHPSAE新浪云 


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

手把手教你在SAE上打造自己的免费天气预报应用
            
    
    博客分类: 天气预报PHP编程 天气PHPSAE新浪云 


 等待片刻,弹出初始化成功对话框时,说明MySQL已经初始化完成了。
手把手教你在SAE上打造自己的免费天气预报应用
            
    
    博客分类: 天气预报PHP编程 天气PHPSAE新浪云 


 关掉对话框,回到MySQL服务管理页面。然后单击“管理MySQL”按钮,打开PHPMyAdmin页面。
手把手教你在SAE上打造自己的免费天气预报应用
            
    
    博客分类: 天气预报PHP编程 天气PHPSAE新浪云 


 在这个页面中我们可以看到,在这个应用的数据库中还没有表,所以我们需要新建一个数据表了。直接用SQL代码进行操作吧,点击上图椭圆框中的SQL按钮,然后输入以下SQL代码,并点击执行,数据表就创建成功了。
手把手教你在SAE上打造自己的免费天气预报应用
            
    
    博客分类: 天气预报PHP编程 天气PHPSAE新浪云 


 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`)
 )
 
手把手教你在SAE上打造自己的免费天气预报应用
            
    
    博客分类: 天气预报PHP编程 天气PHPSAE新浪云 

 

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

 

 

结束语:

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

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

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

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

END

 

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

  • 手把手教你在SAE上打造自己的免费天气预报应用
            
    
    博客分类: 天气预报PHP编程 天气PHPSAE新浪云 
  • 描述: 知天气
  • 大小: 123.2 KB
  • 手把手教你在SAE上打造自己的免费天气预报应用
            
    
    博客分类: 天气预报PHP编程 天气PHPSAE新浪云 
  • 描述: 页面最上边的“我的应用”
  • 大小: 7.8 KB
  • 手把手教你在SAE上打造自己的免费天气预报应用
            
    
    博客分类: 天气预报PHP编程 天气PHPSAE新浪云 
  • 描述: 创建新应用
  • 大小: 10.2 KB
  • 手把手教你在SAE上打造自己的免费天气预报应用
            
    
    博客分类: 天气预报PHP编程 天气PHPSAE新浪云 
  • 描述: 创建一个空应用
  • 大小: 37.7 KB
  • 手把手教你在SAE上打造自己的免费天气预报应用
            
    
    博客分类: 天气预报PHP编程 天气PHPSAE新浪云 
  • 描述: 安全认证
  • 大小: 7 KB
  • 手把手教你在SAE上打造自己的免费天气预报应用
            
    
    博客分类: 天气预报PHP编程 天气PHPSAE新浪云 
  • 描述: SVN菜单
  • 大小: 15.3 KB
  • 手把手教你在SAE上打造自己的免费天气预报应用
            
    
    博客分类: 天气预报PHP编程 天气PHPSAE新浪云 
  • 描述: 代码检出
  • 大小: 46.2 KB
  • 手把手教你在SAE上打造自己的免费天气预报应用
            
    
    博客分类: 天气预报PHP编程 天气PHPSAE新浪云 
  • 描述: 代码检出完成
  • 大小: 83.6 KB
  • 手把手教你在SAE上打造自己的免费天气预报应用
            
    
    博客分类: 天气预报PHP编程 天气PHPSAE新浪云 
  • 描述: 项目文件夹
  • 大小: 25 KB
  • 手把手教你在SAE上打造自己的免费天气预报应用
            
    
    博客分类: 天气预报PHP编程 天气PHPSAE新浪云 
  • 描述: 项目结构
  • 大小: 2.5 KB
  • 手把手教你在SAE上打造自己的免费天气预报应用
            
    
    博客分类: 天气预报PHP编程 天气PHPSAE新浪云 
  • 描述: 添加项目文件到SVN库
  • 大小: 47.7 KB
  • 手把手教你在SAE上打造自己的免费天气预报应用
            
    
    博客分类: 天气预报PHP编程 天气PHPSAE新浪云 
  • 描述: Add对话框
  • 大小: 32.9 KB
  • 手把手教你在SAE上打造自己的免费天气预报应用
            
    
    博客分类: 天气预报PHP编程 天气PHPSAE新浪云 
  • 描述: 增加文件完成
  • 大小: 53.9 KB
  • 手把手教你在SAE上打造自己的免费天气预报应用
            
    
    博客分类: 天气预报PHP编程 天气PHPSAE新浪云 
  • 描述: SVN Commit...
  • 大小: 13.6 KB
  • 手把手教你在SAE上打造自己的免费天气预报应用
            
    
    博客分类: 天气预报PHP编程 天气PHPSAE新浪云 
  • 描述: Commit对话框
  • 大小: 65.4 KB
  • 手把手教你在SAE上打造自己的免费天气预报应用
            
    
    博客分类: 天气预报PHP编程 天气PHPSAE新浪云 
  • 描述: Authentication对话框
  • 大小: 7.5 KB
  • 手把手教你在SAE上打造自己的免费天气预报应用
            
    
    博客分类: 天气预报PHP编程 天气PHPSAE新浪云 
  • 描述: 代码上传完成
  • 大小: 64.8 KB
  • 手把手教你在SAE上打造自己的免费天气预报应用
            
    
    博客分类: 天气预报PHP编程 天气PHPSAE新浪云 
  • 描述: 我创建的应用
  • 大小: 24.5 KB
  • 手把手教你在SAE上打造自己的免费天气预报应用
            
    
    博客分类: 天气预报PHP编程 天气PHPSAE新浪云 
  • 描述: 服务管理--MySQL
  • 大小: 6 KB
  • 手把手教你在SAE上打造自己的免费天气预报应用
            
    
    博客分类: 天气预报PHP编程 天气PHPSAE新浪云 
  • 描述: MySQL服务管理
  • 大小: 8.5 KB
  • 手把手教你在SAE上打造自己的免费天气预报应用
            
    
    博客分类: 天气预报PHP编程 天气PHPSAE新浪云 
  • 描述: MySQL服务初始化成功
  • 大小: 1.4 KB
  • 手把手教你在SAE上打造自己的免费天气预报应用
            
    
    博客分类: 天气预报PHP编程 天气PHPSAE新浪云 
  • 描述: 点击管理MySQL按钮
  • 大小: 15.7 KB
  • 手把手教你在SAE上打造自己的免费天气预报应用
            
    
    博客分类: 天气预报PHP编程 天气PHPSAE新浪云 
  • 描述: PHPMyAdmin页面
  • 大小: 11.3 KB
  • 手把手教你在SAE上打造自己的免费天气预报应用
            
    
    博客分类: 天气预报PHP编程 天气PHPSAE新浪云 
  • 描述: 新建表的SQL代码
  • 大小: 15.3 KB
  • 手把手教你在SAE上打造自己的免费天气预报应用
            
    
    博客分类: 天气预报PHP编程 天气PHPSAE新浪云 
  • 描述: 成功创建了一个数据表
  • 大小: 20.4 KB