这一部分需要实现的是统计数据显示,和访问明细的过滤。最终效果图:


接下来就是把统计数据显示出来。流量概况定义的url为admin/reports/tongji,调用的函数是tongji_view。现在就是完成它。
<?php
function tongji_view(){
//为了方便,我们使用表格来显示数据。根据数据表时的字段,定义一个表格头部信息。
$header = array('日期','总IP','总PV','来自谷歌','来自百度');
$sql = 'SELECT * FROM {tongji} ORDER BY time DESC'. tablesort_sql($header);//查询tongji表里的数据。
$result = pager_query($sql, 10, 0);//以分页形式输出,每页10条。
$rows = array();
while ($a = db_fetch_object($result)) {
$rows[] = array(
$a->time,$a->ip,l($a->pv,'admin/reports/tongji/hits',array('query'=>array('time'=>$a->time))),l($a->google,'admin/reports/tongji/hits',array('query'=>array('time'=>$a->time,'type'=>'google'))),l($a->baidu,'admin/reports/tongji/hits',array('query'=>array('time'=>$a->time,'type'=>'baidu')))
);//五个字段的数据,按日期读取出来。同时链接到访问明细页面,以查看每个项目的明细。
}
$a = db_fetch_object(db_query('SELECT SUM(ip) AS ip,SUM(pv) AS pv, SUM(google) AS google, SUM(baidu) AS baidu FROM {tongji}'));//计算每个项目的总数,并读取出来。
$row = array(
'总计',
$a->ip,
l($a->pv,'admin/reports/tongji/hits'),
l($a->google,'admin/reports/tongji/hits',array('query'=>array('type'=>'google'))),
l($a->baidu,'admin/reports/tongji/hits',array('query'=>array('type'=>'baidu')))
);
if (empty($rows)) {
$rows[] = array(array('data' => '没有数据。你必须开启', 'colspan' => 5));
}else{
$rows[] = $row;
}
$output = theme('table', $header, $rows,array('id'=>'tongji-view'));//输出为表格,调用theme_table
$output .= theme('pager', NULL, 10, 0);//输出分页链接,调用theme_pager
return $output;
}
?>进入这个地址(admin/reports/tongji),如果你正确设置了cron,或者手动导入了数据,页面上就应该会按时间显示出每天的流量的概况了。
然后就是访问明细。访问明细我们直接使用accesslog数据表里的记录,稍做一些过滤,按不同条件列出来即可。每个项目所能显示的数据多少,取决于访问记录的保存时间设置。这儿稍微有些复杂,因为我们需要一些过滤条件。
<?php
//先定义一个表单用来选择过滤条件。
function _tongji_sel(& $form_state){
$form['sel'] = array(
'#type' => 'select',
'#title' => '选择条件',
'#options' => array('all'=>'全部来源','google'=>'来自谷歌','baidu'=>'来自百度'),//设定的条件,可以根据自己的需要设置。
'#default_value' => $_GET['type'],//从url上获取默认数据。
);
$form['tongji-date'] = array(
'#type' => 'textfield',
'#title' => '选择时间',
'#default_value' => $_GET['time'],//传递时间参数。
'#size' => 12
);
$form['submit'] = array(
'#type' => 'submit',
'#value' => '确认',
'#submit' => array('_tongji_sel_submit'),
);
return $form;
}
function _tongji_sel_submit($form, &$form_state) {
$s = $form_state['values']['sel'];
$d = $form_state['values']['tongji-date'];
if($d){
drupal_goto('admin/reports/tongji/hits',array('type' => $s,'time'=>$d));
}else{
drupal_goto('admin/reports/tongji/hits',array('type' => $s));
}//提交后的处理,我们把过滤条件的值(项目和时间)传附加到url上,另一个函数从url上获取参数。
}
function tongji_hits(){
$header = array(
array('data' => t('Timestamp'), 'field' => 'a.timestamp', 'sort' => 'desc'),
array('data' => t('Page'), 'field' => 'a.path'),
array('data' => t('User'), 'field' => 'u.name'),
array('data' => t('Referrer')),
array('data' => t('IP address'))
);//同样以表格方式输出。
if($_GET['time']) {//接收url传递来的时间参数。因为这是管理员使用的,就不必验证参数的合法性了。
$timesql = ' AND to_days(from_unixtime(timestamp)) = to_days('.$_GET['time'].') ';
$allsql = ' WHERE to_days(from_unixtime(timestamp)) = to_days('.$_GET['time'].') ';
$allsql1 = ' WHERE time = '.$_GET['time'];
}
$sql = 'SELECT a.aid, a.path, a.title, a.hostname, a.uid, u.name, a.timestamp,a.url FROM {accesslog} a LEFT JOIN {users} u ON u.uid = a.uid WHERE';
switch ($_GET['type']){//判断url传递来的项目值。根据上面的项目,在这儿使用不同的数据库查询来过滤访问记录。我们上面只定义了三个:全部、百度、谷歌,所以这里也就是三个。
case '':
case 'all':
$result = pager_query('SELECT a.aid, a.path, a.title, a.hostname, a.uid, u.name, a.timestamp,a.url FROM {accesslog} a LEFT JOIN {users} u ON u.uid = a.uid'.$allsql. tablesort_sql($header),30);
break;
case 'google':
$result = pager_query($sql.' a.url LIKE "%%.google.%" '.$timesql. tablesort_sql($header),30);
$title = db_fetch_object(db_query('SELECT SUM(google) AS ip FROM {tongji} '.$allsql1));
break;
case 'baidu':
$result = pager_query($sql.' a.url LIKE "%%.baidu.%" '.$timesql. tablesort_sql($header),30);
$title = db_fetch_object(db_query('SELECT SUM(baidu) AS ip FROM {tongji} '.$allsql1));
break;
case 'yahoo':
$result = pager_query($sql.' a.url LIKE "%%.yahoo.%" '.$timesql. tablesort_sql($header),30);
break;
}
$rows = array();
while ($log = db_fetch_object($result)) {
$rows[] = array(
array('data' => format_date($log->timestamp, 'small'), 'class' => 'nowrap'),
_tongji_format_item($log->title, $log->path),
theme('username', $log),
(($log->url) ? _tongji_keyword($log->url, 40):NULL),
$log->hostname.'<br>'._tongji_getip($log->hostname));
}//读取各字段的数据。这里有两个转换,一个是从来源url中提取搜索关键字,一个是利用QQ纯真IP库来转换ip地址。需要把纯真IP库下载保存到模块文件夹中。
if (empty($rows)) {
$rows[] = array(array('data' => t('No statistics available.'), 'colspan' => 5));
}
drupal_add_js(<<<EOT
$(document).ready(function () {
var type = $("select[@name='sel'] option[@selected]").text();
$('.tj-sels').text(type);
});
EOT
, 'inline');
$output = drupal_get_form('_tongji_sel');
$tm = ($_GET['time'] ? $_GET['time']:'所有时间');
$pv = ($title->pv ? ',总 PV:'.$title->pv:NULL);
$output .= '<h2 class="tj-title">时间段:'.$tm.',<span class="tj-sels"></span> 的总 IP 共:'.$title->ip.$pv.'</h2>';
$output .= theme('table', $header, $rows,array('id'=>'tj-hits'));
$output .= theme('pager', NULL, 30, 0);
return $output;
}
//搜索引擎关键字截取
function _tongji_keyword($v,$w = 35){
$b = urldecode($v);
$x = 1;
if(strpos($v,'.baidu.')){
$q = '/wd=(.*?)&|wd=(.*)/i';
$b = iconv("GBK", "UTF-8", $b);
}elseif(strpos($v,'.google.')){
$q = /[&|
?>$return = '';
if(preg_match("/^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}$/", $ip)) {
$iparray = explode('.', $ip);
if($iparray[0] == 10 || $iparray[0] == 127 || ($iparray[0] == 192 && $iparray[1] == 168) || ($iparray[0] == 172 && ($iparray[1] >= 16 && $iparray[1] <= 31))) {
$t = '本机地址';
} elseif($iparray[0] > 255 || $iparray[1] > 255 || $iparray[2] > 255 || $iparray[3] > 255) {
$t = '- Invalid IP Address';
} else {
$t = _tongji_dataip($ip, drupal_get_path(module,tongji).'/QQWry.Dat');
}
}else{
$t = 'IP地址不合法。';
}
return $t;
}
function _tongji_dataip($ip, $ipdatafile) {
if(!$fd = @fopen($ipdatafile, 'rb')) {
return '- Invalid IP data file';
}
$ip = explode('.', $ip);
$ipNum = $ip[0] * 16777216 + $ip[1] * 65536 + $ip[2] * 256 + $ip[3];
if(!($DataBegin = fread($fd, 4)) || !($DataEnd = fread($fd, 4)) ) return;
@$ipbegin = implode('', unpack('L', $DataBegin));
if($ipbegin < 0) $ipbegin += pow(2, 32);
@$ipend = implode('', unpack('L', $DataEnd));
if($ipend < 0) $ipend += pow(2, 32);
$ipAllNum = ($ipend - $ipbegin) / 7 + 1;
$BeginNum = $ip2num = $ip1num = 0;
$ipAddr1 = $ipAddr2 = '';
$EndNum = $ipAllNum;
while($ip1num > $ipNum || $ip2num < $ipNum) {
$Middle= intval(($EndNum + $BeginNum) / 2);
fseek($fd, $ipbegin + 7 * $Middle);
$ipData1 = fread($fd, 4);
if(strlen($ipData1) < 4) {
fclose($fd);
return '- System Error';
}
$ip1num = implode('', unpack('L', $ipData1));
if($ip1num < 0) $ip1num += pow(2, 32);
if($ip1num > $ipNum) {
$EndNum = $Middle;
continue;
}
$DataSeek = fread($fd, 3);
if(strlen($DataSeek) < 3) {
fclose($fd);
return '- System Error';
}
$DataSeek = implode('', unpack('L', $DataSeek.chr(0)));
fseek($fd, $DataSeek);
$ipData2 = fread($fd, 4);
if(strlen($ipData2) < 4) {
fclose($fd);
return '- System Error';
}
$ip2num = implode('', unpack('L', $ipData2));
if($ip2num < 0) $ip2num += pow(2, 32);
if($ip2num < $ipNum) {
if($Middle == $BeginNum) {
fclose($fd);
return '- Unknown';
}
$BeginNum = $Middle;
}
}
$ipFlag = fread($fd, 1);
if($ipFlag == chr(1)) {
$ipSeek = fread($fd, 3);
if(strlen($ipSeek) < 3) {
fclose($fd);
return '- System Error';
}
$ipSeek = implode('', unpack('L', $ipSeek.chr(0)));
fseek($fd, $ipSeek);
$ipFlag = fread($fd, 1);
}
if($ipFlag == chr(2)) {
$AddrSeek = fread($fd, 3);
if(strlen($AddrSeek) < 3) {
fclose($fd);
return '- System Error';
}
$ipFlag = fread($fd, 1);
if($ipFlag == chr(2)) {
$AddrSeek2 = fread($fd, 3);
if(strlen($AddrSeek2) < 3) {
fclose($fd);
return '- System Error';
}
$AddrSeek2 = implode('', unpack('L', $AddrSeek2.chr(0)));
fseek($fd, $AddrSeek2);
} else {
fseek($fd, -1, SEEK_CUR);
}
while(($char = fread($fd, 1)) != chr(0))
$ipAddr2 .= $char;
$AddrSeek = implode('', unpack('L', $AddrSeek.chr(0)));
fseek($fd, $AddrSeek);
while(($char = fread($fd, 1)) != chr(0))
$ipAddr1 .= $char;
} else {
fseek($fd, -1, SEEK_CUR);
while(($char = fread($fd, 1)) != chr(0))
$ipAddr1 .= $char;
$ipFlag = fread($fd, 1);
if($ipFlag == chr(2)) {
$AddrSeek2 = fread($fd, 3);
if(strlen($AddrSeek2) < 3) {
fclose($fd);
return '- System Error';
}
$AddrSeek2 = implode('', unpack('L', $AddrSeek2.chr(0)));
fseek($fd, $AddrSeek2);
} else {
fseek($fd, -1, SEEK_CUR);
}
while(($char = fread($fd, 1)) != chr(0))
$ipAddr2 .= $char;
}
fclose($fd);
if(preg_match('/http/i', $ipAddr2)) {
$ipAddr2 = '';
}
$ipaddr = "$ipAddr1 $ipAddr2";
$ipaddr = preg_replace('/CZ88\.NET/is', '', $ipaddr);
$ipaddr = preg_replace('/^\s*/is', '', $ipaddr);
$ipaddr = preg_replace('/\s*$/is', '', $ipaddr);
if(preg_match('/http/i', $ipaddr) || $ipaddr == '') {
$ipaddr = '- Unknown';
}
return mb_convert_encoding($ipaddr,"utf-8","gb2312");
}
?>
这样,访问明细的功能就完成了。
| Attachment | Size |
|---|---|
| Drupal模块开发实例(2).zip | 4.5 KB |
谢谢提供这么详细的例子,另外,第二块php代码显示有点问题
谢谢提供这么详细的例子,另外,第二块php代码显示有点问题,好像多了一个?>
Post new comment