记一次换行引发的血案

话说最近真是流年不利,感觉各种BUG犹如天灾一样全部冒出来了,这不昨天又解了一个非常无语的问题,大概是关于换行和正则的臭虫,下面给大家吐槽一下。

数据“野”了

昨天同事反馈某个页面的数据没有正常显示,最开始我还以为是接口没有返回数据,结果看了下请求发现接口有正常的数据呀。没办法就一路反查回去,最后查到居然代码里接口请求抛错了?!因为定义了 Promise 的 catch 流程,所以也没有把错误抛出来。因为之前这个页面都是正常的,很久都没有改动所以我第一反应是这个数据异常了,查了半天的数据格式问题。可是问题就在于明明看到数据是正常的呀,服务端没有报错,接口数据也是可以正常解析的。最后我突然想起来,我们的接口是 JSONP 的会不会是 JSONP 功能挂了?查了一下果然是这样。

Jietu20180616-104611.jpg

阅读全文

批量下载虾米已下载歌曲(新)

前言

呵呵,没错,公子我又再次光荣的把硬盘搞挂了,然后音乐又没了!鉴于之前已经有过一次经验(批量下载虾米已下载歌曲),所以本以为这次也会轻而易举了的。没想到居然在我写出那篇日志后没多久,官方居然各种更新(更新页面,下载机制,Flash播放器),然后我那篇日志的方法就没法用了。不过官方这个也都是小改,所以我也只要小改下代码就成啦!哈哈!

有什么变化

首先要说的是虾米官方的下载思路还是没变的,基本上还是之前日志里头说的那样:

在网站点击下载之后,网站向你的账户中未下载列表传递下载歌曲信息,之后未下载列表则返回一个以emoun://特有协议开头的文件,用以打开虾歌(这个和迅雷thunder://以及电骡等的ed2k://是一个道理)。虾歌打开后查询未下载的表单,返回表单中的歌曲,然后下载。同时将未下载列表中的歌曲提交到已下载列表中,并在未下载列表中删除。 - 批量下载虾米已下载歌曲

官方改变的就是下载列表和网站点击下载这两步:

下载列表

老版的是直接显示列表显示每首歌的,新版则是按照下载时间来显示,一次下载为一次订单,订单内再显示此次下载的歌曲。这样正则匹配获取歌曲的ID就需要发生变化了。

点击下载提交订单

以前只要登陆后向服务器POST歌曲的ID就能提交订单了。新版则需要提交sign_xiamitoken这两个新参数,三个参数一块POST才行。sign参数暂时还不知道如何算出来的,_xiamitoken则是你的cookies。看源码意外的让我发现了参数居然都直接写在页面里头了,为了简便,我就直接抓取订单页面正则获取这两个参数了。同时还加了判断Referer这种老手段,这个也不算难。

VIP机制

以前是没有VIP的,自从被阿里收购之后就增加了VIP功能。好在现在可以用体验点(以前的红包)购买VIP,15个体验点可以买一个月的VIP,一个月的VIP能免费下100首歌曲。我的歌曲数在400+,花了80个体验店办了半年的,可以免费下600首歌曲。等于用80个体验店下600首歌的意思,变相的节省了下体验点,哈哈!

解题步骤

一、获取登陆COOKIES

这一步和老版还是一样的,直接复制过来吧。

获取登陆后的COOKIES文件,方便之后的抓取工作。修改代码中的第2行和第3行,填入自己的账号和密码。如果成功的话,会在该文件的同级目录下得到一个cookies.txt文件。

<?php
$name = ''; //输入你的账号
$password = ''; //输入你的密码
$curl_post = 'email='.$name.'&amp;password='.$password.'&amp;done=/&amp;submit=登 录';
$cookie_file = dirname(__FILE__).'/cookie.txt';
$curl = curl_init();
curl_setopt($curl, CURLOPT_URL, &quot;http://www.xiami.com/member/login&quot;);
curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($curl, CURLOPT_POST, 1);
curl_setopt($curl, CURLOPT_POSTFIELDS, $curl_post);
curl_setopt($curl, CURLOPT_COOKIEJAR, $cookie_file);
curl_exec($curl);
curl_close($curl);
?>

二、抓取下载列表并提交到未下载列表

这一步因为列表的改变有些许变化。而且新版订单还有个新订单和旧订单之分,真是蛋疼,还得做两次解析。

<?php
set_time_limit(0); //设置成不限制页面运行时间
function get($url) {
    $cookie_file = dirname(__FILE__).'/cookie.txt';
    $curl = curl_init($url);
    curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);
    curl_setopt($curl, CURLOPT_COOKIEFILE, $cookie_file);
    $data = curl_exec($curl);
    curl_close($curl);
    return $data;
}
$song = array();
$pageinfo = get('http://www.xiami.com/account/myorders-old');
$preg = '/\…\<\/a\>\<a href\=\"\/account\/myorders-old\/page\/(.*?)\" class\=\"p\_num\">/s';
preg_match_all($preg, $pageinfo, $match);
$page = $match[1][0];
for($i=1;$i<$page;$i++) {
    $data = get("http://www.xiami.com/account/myorders-old/page/".$i);
    $preg = '/\<td class\=\"iname\"\>\<a href\=\"\/song\/(.*?)\"/s';
    preg_match_all($preg, $data, $match);
    foreach($match[1] as $item) $song[] = $item;
}
$pageinfo = get('http://www.xiami.com/account/myorders');
$preg = '/\…\<\/a\>\<a href\=\"\/account\/myorders\/page\/(.*?)\" class\=\"p\_num\">/s';
preg_match_all($preg, $pageinfo, $match);
$page = $match[1][0];
for($i=1;$i<$page;$i++) {
    $data = get("http://www.xiami.com/account/myorders-old/page/".$i);
    $preg = '/\<td class\=\"iname\"\>\<a href\=\"\/song\/(.*?)\"/s';
    preg_match_all($preg, $data, $match);
    foreach($match[1] as $item) $song[] = $item;
}
$song = array_unique($song, SORT_NUMERIC);
echo 'var song = new Array('.implode(',', $song).')';
?>

批量提交下载歌曲

我之前也讲了,新版新增sign_xiamitoken两个参数,同时还增加了Referer验证。整体代码还是采用上版中的PHP+AJAX异步提交,只是在PHP部分有稍许修改。

将上一步得到的代码复制替换掉相同的那部分,保存为download.html

<script type="text/javascript">
//将第二步获得的代码复制到下面
var song = new Array(1769629171,3338870,1769902385,1770432131,2868586,1770149760,367633,1769832130,35526,1769962750,1770551145,1770457081,3486103,1769400110,127903,3367334,2078855,71830,376007,376015,2074918,2730,1770450144,3455520,79157,79151,81366,65256,390070,2138604,1770345727,376050,376006,149193,388168,1769665592,3497062,1769236069,3632104,1768923954,1769491757,3608275,2092882,1770354410,3480460,3620143,2095376,2561774,3664677,1770462404,1769056924,3527076,2126340,2089410,1769177482,2083322,1769831952,1769316186,1770524409,1769517803,1190507,1964547,1769107542,3486203,1769686818,1769028326,1858814,2084011,1769235816,1770614545,2083187,2605276,378268,2515019,1122167,1769176497,3302053,2083102,3638520,189072,371017,1770168732,1083760,2122948,2070331,2128868,3319126,2561592,1381654,3441719,1768939471,2091290,2098665,2067235,1770060224,3562953,54342,1769831786,1770145312,76323,2067242,173117,136054,1770068043,1769833104,1769833105,1769833106,1769833107,1769833108,2082305,1768989931,1769356638,1769082273,1769776879,1769740304,1205851,1768984809,1769102373,1769740095,1768989928,1769381931,1769227674,3599015,1768962602,3463177,1769381938,1769381935,1769381934,1769381932,3410377,2067242,3381901,3381903,373969,2072395,373971,373990,374039,3381910,3381911,3381912,382134,378711,193010,162269,143775,127673,120041,89443,52732,382512,383210,1769274527,1769004670,1768958960,3599311,3365855,2314604,2080987,2073790,385907,115384,374057,377936,380029,382560,382852,383962,33806,378041,380287,385729,385760,388406,389153,381833,83126,386773,389072,389080,389077,43542,52726,375183,382821,384595,385074,386954,373818,376387,378307,379302,382777,384646,384670,385137,385976,386073,386347,2342433,3550893,1769699970,2095102,2095107,2017034,2286524,2342421,2286523,3338183,1768988423,2286527,2380720,3464931,1176114,1769334977,2155384,1769839800,3225258,2091936,1769334987,3187867,2095104,3413844,1769072635,1007695,3636957,3467770,1768940269,1769292436,1769850021,1769102619,3409064,1769870173,1769850022,1769850019,1769463117,3446206,2028877,2136483,1769072646,1769291745,1769072643,1769113798,196142,3187959,2079575,2286522,2079581,2385273,1769673320,3513664,1769071426,3502285,1769801604,1769801605,3484274,1769303054,1769303056,1769303057,1769303058,1769303059,1769303060,1769303061,1769303062,1769303055,1768914983,378646,3586293,1769830111,1769830112,1769830113,1769830114,1769830115,1769830116,1769830117,1769830118,1769830119,1769830120,1769570445,);

//复制结束

//下面的代码不需要修改 
var XHR; //定义一个全局对象 
function xm_download(id){  
    if(window.ActiveXObject){//IE的低版本系类 
        XHR=new ActiveXObject('Microsoft.XMLHTTP');
    }else if(window.XMLHttpRequest){//非IE系列的浏览器,但包括IE7 IE8 
        XHR=new XMLHttpRequest(); 
    } 
    XHR.open("GET","download.php?id="+id,true);        
    XHR.send(null); 
} 
for (var i=0;i<song.length;i++) {
    xm_download(song[i]);
}
</script>

将下面的代码保存为download.php,放在与download.html同级目录中

<?php
$cookie_file = dirname(__FILE__).'/cookie.txt'; //登陆COOKIES文件地址
$id = $_GET['id'];
$url = "http://www.xiami.com/download/pay?id=$id";
$curl = curl_init($url);
curl_setopt($curl, CURLOPT_COOKIEFILE, $cookie_file);
curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);
$data = curl_exec($curl);
curl_close($curl);
$preg = '/\<input type\=\"hidden\" name\=\"sign\" id\=\"sign\" value\=\"(.*?)" \/\>/s';
preg_match_all($preg, $data, $match);
$sign = $match[1][0];
$pieces = explode('<input type="hidden" value="', $data);
$piece = end($pieces);
$cookies = explode('"', $piece);
$cookie = $cookies[0];
$data = "song_ids[]=$id&amp;use_vip=1&amp;down=1&amp;inpour_amount=0&amp;sign=$sign&amp;_xiamitoken=$cookie";
$curl = curl_init($url);
curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($curl, CURLOPT_POST, 1);
curl_setopt($curl, CURLOPT_COOKIEFILE, $cookie_file);
curl_setopt($curl, CURLOPT_REFERER, $url);
curl_setopt($curl, CURLOPT_POSTFIELDS, $data);    
$data = curl_exec($curl);
curl_close($curl);
?>

四、打开虾歌查询订单

最后一步是打开虾歌,选择“文件”→“检查未完成下载”,静候片刻你就可以欢呼了!之后静静等待虾歌批量下载成功就好了。

PMBlog

PMBlog是我最近写个一个markdown静态化输出的小程序。目前能够实现发布文章和页面,自定义模板等基本功能。虽然PHP干这活可能亚历山大,不过PHP搭配起来简单而且做中小型博客的话应该是没有问题的。

目前更新到4.0版,采用权限的模板引擎Twig,并更换仓库到Github上,欢迎大家继续使用。

官方站点:http://lizheming.github.io/PMBlog

项目地址:http://github.com/lizheming/PMBlog

官方站点:http://lizheming.gitcafe.com

项目地址:HTTPS://GitCafe.com/lizheming/PMBlog

安装方法

  1. 搭配本地PHP环境

  2. 下载代码并修改config.php

  3. 访问index.php即会在html目录生成静态文件

Markdown文件书写规则

默认文件名是输出的静态页面的文件名,即'hello-world.md'将会生成'hello-world.html'。另外不推荐使用中文名作为文件名。

markdown(以下简称md)文件支持一些自定义字段。

  • 文件开头输入"title: Hello World"即可自定义文章标题为"Hello World"(必写字段)

  • "date: 2013年2月11日"即可自定义文章发布时间,如果不定义此字段程序会返回文件的创建时间为文章发布时间(可选字段)

  • "type: page"即可自定义本篇文章为页面,此字段只接受page/post两个参数,不定义此字段默认返回为post(可选字段)

  • "status: draft"即可自定义本篇文章为草稿,定义为草稿的文章将不被程序输出。此字段只接受draft一个参数,非该参数无效。不定义此字段则默认该文章为发布状态(可选字段)

  • "tags: tag1, tag2"即可自定义该文章的关键词,各个关键词之间使用半角逗号分开(可选字段)

也就是说目前最简单的写法就是只要定义一个"title:"字段然后开始正文就好了。

虾米自动签到的实现

前言

今天抽空整理了下把它写成了一个多账号版本的,放在了SAE上头,网址是:http://autocheck.sinaapp.com 。 上头输玩账号密码程序就可以自动帮你的账号签到了。切记程序会记住你的账号密码,如果有介意的请千万不要使用,本人不对你的账号问题进行负责。

上一篇文章中,我们讲述了如何利用PHP批量下载虾米已下载的歌曲。其中我们实现了如何用PHP+CURL模拟虾米登陆,这回我们来实现一下如何自动签到。(对于我这样的只是拿虾米当下载音乐的地方,而且经常忘记签到的孩子真的是非常有用啊有木有!T_T)

一、获取登陆COOKIES

还是老样子,我们先获取到登陆的COOKIES文件。修改代码中的第2行和第3行,填入自己的账号和密码。如果成功的话,会在该文件的同级目录下得到一个cookies.txt文件。

$name = ''; //输入你的账号
$password = ''; //输入你的密码
//获取登陆cookie
$curl_post = 'email='.$name.'&password='.$password.'&done=/&submit=登 录';
$cookie_file = dirname(__FILE__).'/cookie.txt';
$curl = curl_init();
curl_setopt($curl, CURLOPT_HEADER, 1);
curl_setopt($curl, CURLOPT_URL, "http://www.xiami.com/member/login");
curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($curl, CURLOPT_POST, 1);
curl_setopt($curl, CURLOPT_POSTFIELDS, $curl_post);
curl_setopt($curl, CURLOPT_COOKIEJAR, $cookie_file);
curl_exec($curl);
curl_close($curl);

二、获取签到地址

虾米的签到其实是向http://www.xiami.com/task/signin这个网页发送一个POST,这个POST的Data长度是0。代码利用虾米手机页面的签到机制,向一个特定的地址发送一个POST过去就可以了。所以再要就是获取签到的地址。

三、进行签到

利用上一步中获取到的地址进行签到。但是要注意的是,网页会判断页面来源,如果不是从虾米网站POST过去的会签到失败。所以我添加了自定义Referer来源。之前就一直因为这个没有更改而一直都没有成功,后来索性模拟了所有的HTTP Header才发现了问题的所在。另外,虽然POST空数据过去,但千万不要以为不POST数据过去就行了,无和0还是有点区别的,哈哈!其它的就没有什么问题了。签到成功的话页面会返回你的签到天数。

//自动签到
$url = 'http://www.xiami.com' . $match[1][0];
$curl = curl_init();
curl_setopt($curl, CURLOPT_URL, $url);
curl_setopt($curl, CURLOPT_COOKIEFILE, $cookie_file);
curl_setopt($curl, CURLOPT_HEADER, 1);
curl_setopt($curl, CURLOPT_REFERER, 'http://www.xiami.com/web');
curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);
$num = curl_exec($curl);
curl_close($curl);

四、Cron添加自动签到任务

我这里以SAE为例,将第一步获取到的cookies.txt文件和第二步的xiami.auto.sign.php一起上传到应用中。例如存放位置是/xiami。在cron.yaml末尾添加如下代码:

  - description:cron XiamiAutoSign
    url: xiami/xiami.auto.sign.php
    schedule: every day of month 00:10
    timezone: Beijing
设置成功的话会在每天的00:10访问这个页面,完成自动签到功能!

如何批量下载虾米已下载歌曲

本文方法已失效,新版见:如何批量下载虾米已下载歌曲(新)

前言

首先要说明的是,这不是一篇讲述如何免费批量下载虾米高质量音乐的文章,而是讲述一个杯具男如何因为懒惰而DIY出的成果。所以如果抱有前述心理的同学到此可以关闭网页了。另外本文中代码运用到了PHP+CURL+JavaScript,推荐大家在本地环境中进行操作。同时最重要的是,本文不是讨论如何绕过虾米的收费机制下载歌曲,所以你必须保证你有足够的虾米币或者红包用来下载歌曲才行,否则一切免谈。

事出有因

事情是这样的。前两天安装了Linux Mint,在Linux中打开了音乐,没过一会儿就卡掉了,当时我也没在意。结果一回到Windows就提示我文件夹损坏了,里面的文件也自然都悲剧了。用恢复软件恢复了效果也不太理想。400首歌总共2G多的文件也不是说割舍就能割舍的,所以就有了下面这些。

解题思路

虾米下载的机制是这样的:在网站点击下载之后,网站向你的账户中未下载列表传递下载歌曲信息,之后未下载列表则返回一个以emoun://特有协议开头的文件,用以打开虾歌(这个和迅雷thunder://以及电骡等的ed2k://是一个道理)。虾歌打开后查询未下载的表单,返回表单中的歌曲,然后下载。同时将未下载列表中的歌曲提交到已下载列表中,并在未下载列表中删除。这样,一次下载就完成了。

download

如图所示,点击下载歌曲,网站向http://www.xiami.com/download/song页面POST提交了相关Data,同时网页返回一个emoun://协议开头的文件(图中左侧红色方框标记的)。

所以我的想法是这样的:首先登陆网页抓取已下载列表中已经下载过歌曲的信息,然后批量的提交到未下载列表。然后打开虾歌去查询未下载列表中的歌曲就好了。如果和我所想一样的话,虾歌应该会一次性批量得到所有歌曲,那么我们只要等待下载完成就好了。

解题步骤

一、获取登陆COOKIES

获取登陆后的COOKIES文件,方便之后的抓取工作。修改代码中的第2行和第3行,填入自己的账号和密码。如果成功的话,会在该文件的同级目录下得到一个cookies.txt文件。

$name = ''; //输入你的账号
$password = ''; //输入你的密码
$curl_post = 'email='.$name.'&password='.$password.'&done=/&submit=登 录';
$cookie_file = dirname(__FILE__).'/cookie.txt';
$curl = curl_init();
curl_setopt($curl, CURLOPT_URL, "http://www.xiami.com/member/login");
curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($curl, CURLOPT_POST, 1);
curl_setopt($curl, CURLOPT_POSTFIELDS, $curl_post);
curl_setopt($curl, CURLOPT_COOKIEJAR, $cookie_file);
curl_exec($curl);
curl_close($curl);

二、抓取下载列表并提交到未下载列表

有了上一步之后,这一步就变的非常的简单。这里主要考虑的是效率的问题,由于我的歌曲打开400首,虾米一页显示20首。所以我大概有20页要抓取,这对于PHP来说是一个不小的工作量,在本地运行更甚。如果你的页面少可以使用下面的代码,如果你要抓的页面多,可以尝试将其改写成multi\_curl同步抓取,或者改写成AJAX形式,亦或是分批抓取都行。使用代码时候记得修改第三行的抓取页数。

set_time_limit(0); //设置成不限制页面运行时间
$page = ''; //填写你的已经下载页面的页数
$cookie_file = dirname(__FILE__).'/cookie.txt';

$song = '';
//如果页数过多可以分批获取,以免等待时间过长
for($i=1;$i<=$page;$i++) {
$curl = curl_init();
curl_setopt($curl, CURLOPT_URL, "http://www.xiami.com/account/mysongs/s/2/page/".$i);
curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($curl, CURLOPT_COOKIEFILE, $cookie_file);
$data = curl_exec($curl);
curl_close($curl);

$preg = '/\<td.class\=\"iname\"\>\<a.href\=\"\/song\/(.*?)\"\>(.*?)\<\/a\>/s';
preg_match_all($preg, $data, $match);
foreach($match[1] as $item) {
    $song .= $item . ',';
}

}
$song = str_replace(' ', '', $song);
$song = substr($song, 0, -1);
echo "var song = new Array($song);";
/end/

三、批量提交下载歌曲

上一步的代码中,我将下载歌曲的ID输出成了JavaScript数组的形式。因为这一步中我们将以歌曲数为基数向虾米网站POST提交信息,400对于PHP来说仍然是一个庞大的数字,对于本地更甚。你可以修改成multi_curl的形式,不过我第一反应是AJAX异步传输,这就是为什么我将歌曲的ID输出成了JavaScript数组的原因。

原理很简单,JS用来模拟循环,PHP则负责POST提交数据。使用代码时记得将xiami.song.download.html中的第3行替换成你在上一步中获得的代码。


$data = 'pid=&ptype=&song_count=1&id='.$_GET['id'];     
$cookie_file = dirname(__FILE__).'/cookie.txt'; //登陆COOKIES文件地址
$curl = curl_init();
curl_setopt($curl, CURLOPT_URL, "http://www.xiami.com/download/song");
curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($curl, CURLOPT_POST, 1);
curl_setopt($curl, CURLOPT_COOKIEFILE, $cookie_file);
curl_setopt($curl, CURLOPT_POSTFIELDS, $data);  
$data = curl_exec($curl);
curl_close($curl);

四、打开虾歌查询订单

最后一步是打开虾歌,选择“文件”→“检查未完成下载”,静候片刻你就可以欢呼了!之后静静等待虾歌批量下载成功就好了。

公子手把手教你写留言板程序

网络上各种各样的PHP教程和各种各样的留言板都是铺天盖地的,战地为什么要自己写一个这样的PHP留言板教程呢?问的好啊!鼓掌。首先战地写这个PHP教程的目的不是为了做一个留言板,如果你需要一个留言板的话我建议你去Google搜索一下免费的、功能强大的、功能齐全的、 漂亮的到处都是。目的是:从一个简单的实际的案例出发,来让想学习PHP的兄弟姐妹们进入PHP的世界。需要说明的是,既然是实际的案例教程,各种各样的知识都会涉及到(以保证各位遇到更多的问题),阅读这个教程的时候你最好了解一点Html和 javascript的知识,因为在教程中将不作为重点来说。因为我们是PHP教程。

好了,现在说说我们将要设计的知识和这个留言板将要实现的功能:
功能需求:利 用PHP+Mysql数据库制作一个基本的留言板能够让客户进行留言,管理员可以对留言进行修改、删除、回复等操作。

在进行下面的学习之前,希望大家能够下载我编写的源码边看边学,这样能达到最好的效果。源码下载请点击这里。拿到源码请先看README文件

1.文件结构的功能的架设

为了制作一个留言板首先我们需要考虑好要创建什么东西。首先需要一个单独存放数据库信息的config.php文件,然后当然是index.php。当然还需要有表单数据处理的action.php文件,已经函数归类的function.php文件。哦,不要忘记了,留言板需要管理员登陆的,所以还要一个login.php文件。

也就是我我们需要创建5个文件,功能分别如下:

  • 1.index.php - 首页显示留言框和留言等信息的
  • 2.config.php - 记录数据库信息的
  • 3.action.php - 接受表单数据进行数据库处理的
  • 4.function.php - 函数归档文件
  • 5.login.php - 管理员登陆页面

2.需要掌握的PHP知识和常用函数

通过查看源码可以看出基本需要的几个函数分别是:ehco,if,while,switch,require_once,header等。另外你还需要了解COOKIE和SESSION两个东东。下面我会一一为大家解释一下

1.PHP语句的写法

PHP 的语句以 <?php 开始,以 ?> 结束。您可以把 PHP 的脚本块放置在文档中的任何位置。当然,在支持简写的服务器上,您可以使用 来开始和结束脚本块。不过,为了达到最好的兼容性,我们推荐您使用标准形式 (<?php),而不是简写形式。实际操作中并不是一个<?php ?>包括所有的东西,而是运用了HTML和PHP混排的效果,即需要使用PHP语言的地方用,不需要的时候就不用。

2.PHP变量

PHP 中的变量变量用于存储值,比如数字、文本字符串或数组。一旦设置了某个变量,我们就可以在脚本中重复地使用它。PHP 中的所有变量都是以 $ 符号开始的。

3.PHP字符串

这个我就不多做介绍了,基本上和数学差不多。但大家要注意以下的是,PHP中%是取余的计算符号,在常量/变量前加!是表示非的意思,=是赋值的符号(即将等号右边的值赋给等号左边的东西)。而如果你想使用等于这个符号的话,必须使用 ==

4.echo书写

PHP输入文本的基本指令

5.if条件

当您编写代码时,您常常需要为不同的判断执行不同的动作,您可以在代码中使用条件语句来完成此任务。
if{} 语句
在条件成立时执行一块代码,否则跳过该语句
if...else 语句
在条件成立时执行一块代码,条件不成立时执行另一块代码
elseif 语句
与 if...else 配合使用,在若干条件之一成立时执行一个代码块

6.while循环

在您编写代码时,您经常需要让相同的代码块运行很多次。您可以在代码中使用循环语句来完成这个任务。while语句能够帮助你执行这个动作,只要指定的条件成立,while 语句将重复执行代码块。

7.switch选择

如果您希望有选择地执行若干代码块之一,请使用 Switch 语句。
工作原理:

  • 1.对表达式(通常是变量)进行一次计算
  • 2.把表达式的值与结构中 case 的值进行比较
  • 3.如果存在匹配,则执行与 case 关联的代码
  • 4.代码执行后,break 语句阻止代码跳入下一个 case 中继续执行
  • 5.如果没有 case 为真,则使用 default 语句

8.require_once包含

通过require_once语句,能够将另外的文件添加进当前文件中,对文件的引用非常有帮助

9.header信息

通过header函数,你可以在PHP中定义一些HTML页面中<head></head>提供的信息,例如本代码中就经常使用header进行跳转操作。

10.自定义函数

我们能够将我们经常需要用到得一大堆步骤打包成一个函数,方便自己的使用。例如数据库的操作等...

创建 PHP 函数:

  • 所有的函数都使用关键词 "function()" 来开始
  • 命名函数 - 函数的名称应该提示出它的功能。函数名称以字母或下划线开头。
  • 添加 "{" - 开口的花括号之后的部分是函数的代码。
  • 插入函数代码
  • 添加一个 "}" - 函数通过关闭花括号来结束。

3.PHP和数据库的基本交互

1.表单

程序的基本目的是通过PHP获取用户输入的留言信息,然后传递给数据库进行读取与编辑。但是这些信息是如何传递给数据库的呢,这就需要引用表单的概念。表单内获得的数据能够非常轻松的传递给各个地方。一个<form></form>即为一个表单,表单需要制定action和method两个属性,action属性是指表单获取到得数据要传递的终点站,而method的值是指定传输的方法,有GET和POST两种方法,GET是通过URL地址传输过去,而POST不是通过URL传说的。也就是说设置在URL中的值能够方便的通过GET方法来获取。表单内一般使用<input>输入框来让用户输入信息,input输入框必须要有name属性,通过name属性,表单才能调用该输入框的输入信息。如果你要知道更加详细的信息,可以看看这里

2.数据库的基本操作

想要对数据库进行操作,首先必须要连接(Connect)数据库。用户的留言是需要输入(Insert)进数据库的,管理员删掉留言是对数据库进行删除(DELETE)操作的。操作完成之后我们必须关闭(CLOSE)与数据库的连接。每次对数据库进行操作,我们都必须进行一次连接与断开连接的操作,为了方便自己,可以把这一个操作写成自定义函数的形式。(本示例中包装成了sql_query函数,在function.php第3行)

4.开始写留言板程序

1.创建数据库

这里我以PHPmyadmin为例,进入到如图所示的界面然后输入如下代码并点击执行。这样数据库就建立好了。

--
-- 数据库: `guestbook`
--
CREATE DATABASE `guestbook` DEFAULT CHARACTER SET latin1 COLLATE latin1_swedish_ci;
USE `guestbook`;
-- 如果是在已经存在的表中建立,则将上面的代码去除后执行即可
-- --------------------------------------------------------
-- 需要建立的表有entry,user,如果有重名的表,修改相关代码执行即可
--
-- 表的结构 `entry`
--

CREATE TABLE IF NOT EXISTS entry (
id int(10) NOT NULL AUTO_INCREMENT,
username varchar(255) CHARACTER SET utf8 COLLATE utf8_unicode_ci NOT NULL,
content mediumtext CHARACTER SET utf8 COLLATE utf8_unicode_ci NOT NULL,
time int(10) NOT NULL,
email varchar(255) CHARACTER SET utf8 COLLATE utf8_unicode_ci NOT NULL,
website varchar(255) CHARACTER SET utf8 COLLATE utf8_unicode_ci NOT NULL,
agent varchar(255) CHARACTER SET utf8 COLLATE utf8_unicode_ci NOT NULL,
ip varchar(15) CHARACTER SET utf8 COLLATE utf8_unicode_ci NOT NULL,
geo varchar(255) CHARACTER SET utf8 COLLATE utf8_unicode_ci NOT NULL,
PRIMARY KEY (id)
) ENGINE=MyISAM DEFAULT CHARSET=latin1 AUTO_INCREMENT=1 ;

--
-- 表的结构 user
--

CREATE TABLE IF NOT EXISTS user (
id int(10) NOT NULL AUTO_INCREMENT,
username varchar(255) CHARACTER SET utf8 COLLATE utf8_unicode_ci NOT NULL,
password varchar(255) CHARACTER SET utf8 COLLATE utf8_unicode_ci NOT NULL,
PRIMARY KEY (id)
) ENGINE=MyISAM DEFAULT CHARSET=latin1 AUTO_INCREMENT=2 ;

--
-- 转存表中的数据 user
--

INSERT INTO user (id, username, password) VALUES
(1, 'admin', '21232f297a57a5a743894a0e4a801fc3');

2.用户数据的提交和写入数据库

上面说了,数据的交互我们需要用到表单,所以要新建立一个表单,代码如下:

昵称: 邮箱: 网站: 你可以使用的标签有:<a>,<img>,<p>,<br>,<b>

如代码所示,如上我们就能够通过$_POST['username'],$_POST['email'],$_POST['website'],$_POST['content']分别获取用户的昵称,邮箱和网址已经留言内容等信息。这些信息的接受文件是action.php,那么我们需要在action.php中写入数据库的相关操作。(实例代码中将许多表单中的操作放到一个文件中了,为了代码的方便,所以添加了switch选择函数,而选择的对象则是通过GET方法从URL中获取的)

  if (!$_SESSION['login']) {//判断用户是否登录,如果没登陆执行以下操作
     $username = $_POST['username'];//赋值
     setcookie('gbook_name',$username,time()+ 604800);//设置COOKIE
     $email = $_POST['email'];
     setcookie('gbook_email',$email,time()+ 604800);
     $website = $_POST['website'];
     setcookie('gbook_website',$website,time()+ 604800);
  } else {//登录的话执行以下操作
    $user = sql_query ('SELECT * FROM user WHERE username = "admin"');//读取用户数据
    $user = mysql_fetch_object($user);//对取得的数据进行格式化
    $username = $user -> nickname;//赋值管理员昵称
    $email = $user -> email;
    $website = $user -> url;
  }
     $content =  $_POST['content'];
     $ip = getip();//通过getip函数获取用户IP
     $geo = user_ip($ip);//通过user_ip函数对IP地址进行解析,得到详细地质
     if ($geo = "") {
       $geo = "火星";//如果没IP或解析不到则显示为火星
     }
     $agent = $_SERVER[HTTP_USER_AGENT];//记录使用者的操作系统信息
     if ($username !=="" && $content !== "" ) {//如果昵称和留言内容都不为空则执行以下内容
       $post_time = time();//获取时间
     $content = strip_tags($content,'

');//对留言内容进行格式化 $insert_sql = "INSERT INTO entry (id, username, content, time, email, website, agent, ip, geo) VALUES ('','$username','$content','$post_time','$email','$website','$agent','$ip','$geo')"; sql_query($insert_sql);//将留言内容写入数据库 header('Location:index.php');//跳转回首页 } else {//如果昵称和留言内容二者有一个为空则执行以下语句 echo ""; }

我为这段代码进行了详细的解释,大家应该都能看的懂了。这里需要注意的是读取出来的SQL信息首先都必须对其进行格式化,可以选择的格式化函数有mysql_fetch_object,mysql_fetch_array等,这里选择了第一个。格式化后的信息就可以通过“信息 -> 字段名”的方式来获取相应字段的内容。

3.显示留言内容

通过对entry表进行SELECT读取操作显示最近的留言,整体的代码如下:

  • <?php echo $entry -> username; ?> username;?> 来自 geo; ?> agent); ?> content);/*nl2br是将换行变成
    的函数,不需要太多了解*/ ?>
    发表于 time);/*通过自定义函数对Unix时间戳进行格式化并得到距离现在的时间*/ ?> [回] [删]

通过上一小节的学习,我想大家对上面这段代码应该基本上能懂了,我就不多做解释了。

5.分页效果的制作

其实分页就是考察你的计算能力,假如你每页显示10条内容,则你第i页显示的消息起始数为第[(i-1)*10+1]条,而第i页我们可以利用GET方法从URL地址中获取。通过ORDER BY 能够对数据进行顺序排列,而ORDER BY DESC能够对数据进行倒序排列。再添加上LIMIT a,b就可以自定义从数据的第a条开始取,一直取b条出来。创建成自定义函数之后就变成了

function get_entry_by_page($perpage) {
  if ($_GET['page'] == "") {//设置当前页的默认值为1
    $_GET['page'] = 1;  
  } 
  $page = $_GET['page'];
  $start_entry = ($page - 1) * $perpage;//$prepage为你设置的每页显示的条数
  $entrys = sql_query('SELECT * FROM entry ORDER BY time DESC LIMIT ' . $start_entry . ', ' . $perpage);
  return $entrys;   
}

除了做内容的分页,我们还需要做一个翻页的按钮才行,这个也是基本的计算问题,你们可以尝试的去理解一下。

function pages($perpage) {
  $count = sql_query("SELECT COUNT(id) AS total FROM entry"); 
  $count = mysql_fetch_object($count);
  $count = $count -> total;//获取总条数
  if ($count%$perpage == 0) {
    $page_total = intval($count/$perpage);  
  } else {
    $page_total = intval($count/$perpage) + 1;  
  }//获取总页数
  if ($_GET['page'] == "") {
    $_GET['page'] = 1;  
  }
  $page_class = 'page';
  echo '';
  if ($_GET['page'] != 1) {
    $pre_page = $_GET['page'] - 1;
    echo '«上一页';      
  }
  if ($page_total <= 5 ) {
    for ($i=1;$i <= $page_total;$i++) {
      echo '' . $i . '';   
    }   
  } else {
    for ($i=1;$i <= 5;$i++) {
      echo '' . $i . '';           
    }   
    echo "...";
    echo '' . $page_total . '';       
  }
  if ($_GET['page'] != $page_total ) {
    $next_page = $_GET['page'] + 1;
    echo '下一页»'; 
  }
  echo '';
}

6.管理员的登陆

对这个功能编写前,你们必须了解SESSION的相关知识,如果不知道请点这里我们对用户提交过来的用户名和密码进行校验,如果匹配就把$_SESSION['login']赋值为真(true),否则就告诉用户登录失败。密码是采用md5加密方法存储到数据库里面的。详细代码可以参看login.php文件已经action.php文件。

5.总结

本篇文章知识草草的从我的角度上编写了一个简单的教程,对某些简单的问题可能讲的过于繁琐,当然可能对某些复杂的问题避而不讲。所以大家在遇到不懂的问题的时候,希望能够善于利用搜索引擎来帮助自己更好的理解这篇文章。按照步骤来基本上不会出什么错,如果有出错了,首先一定要记得检查一下是不是你的书写有问题,是不是少了一个s,或者是少了一个;等等。

本文章中的专业性知识的讲解部分是引用自W3school。W3school是一个不错的网络入门学习网站,推荐大家去看一看。

引用豆瓣最近读过的书和看过的电影

前几天在捣鼓我的PageCookery主题的时候想引用豆瓣上我最近看过的电影和书,当时只是手工自己写上去的而已。我度过的书到还是好说,一年也难得有一本,但是电影就多了,手写也不是办法。于是开始研究起豆瓣的API了。发现豆瓣输出的是Atom和Json的结果,恩,我用的是Atom的,想要Json版的请看传送门

效果预览请见传送门,详细代码如下:

function Douban($username, $subject, $apikey)
{   
if ($apikey == "")
{
  $apikey='064e10081295144112ea301837bf3cc3';
}
$douban='http://api.douban.com/people/' . $username . '/collection?cat=' . $subject . '&apikey=' . $apikey ;
$feed =  simplexml_load_file($douban);
$children =  $feed->children('http://www.w3.org/2005/Atom');
$a = $children-> entry->children('http://www.w3.org/2005/Atom')->xpath('//db:subject');
echo '
    '; foreach ($a as $d) echo '
  • ' . $d -> title . '
  • '; echo '
'; }

我把它定义成了一个函数Douban,WP就放到主题的function.php下,PageCookery就放到/lib/function_microblog.php里,其它的自己看着办咯。引用的时候只要如下形式即可

< ?php Douban('lizheming', 'movie' , '');//形式是昵称|收藏类型|API_KEY ?>
收藏类型有movie|book|music三种类型可以选择,API_KEY我设置了如果为空则默认一个,但是我还是希望大家可以自己去申请一个,因为豆瓣的api有引用频率的限制,如果一个api_key很多人同时用,可能会出问题。如果使用上有什么问题,大家可以留言。

参考资料:PHP中的SimpleXML处理//对SimpleXML的描述很详细,推荐!