要在Discuz!论坛中实现显示访问者最近三个来路网址,可以按照以下步骤操作。这涉及到获取来路网址、存储这些信息,并在页面上显示最近的三条记录。下面将详细解答你的三个问题:
### 1. 如何知道来我网址的人是从哪个网址来的
在Web开发中,可以通过HTTP请求头中的`HTTP_REFERER`字段获取访问者的来路网址。不过需要注意的是:
- **可靠性**:`HTTP_REFERER`并非总是存在,有些浏览器或防火墙可能会禁用它,或者用户可能直接输入网址访问,这时`HTTP_REFERER`将为空。
- **安全性**:`HTTP_REFERER`可以被伪造,因此不应依赖它进行安全验证。
在Discuz!中,可以通过PHP代码获取`HTTP_REFERER`。例如,在模板文件中,你可以这样获取:
```php
<?php
$referer = isset($_SERVER['HTTP_REFERER']) ? $_SERVER['HTTP_REFERER'] : '';
?>
```
### 2. 如何显示来路网址
要在页面上显示来路网址,首先需要将获取到的`HTTP_REFERER`存储起来,然后在模板中进行显示。以下是具体步骤:
#### a. 存储来路网址
你需要创建一个数据库表来存储来路网址。假设你已经熟悉Discuz!的数据库结构,可以按照以下步骤操作:
1. **创建数据库表**
在Discuz!的数据库中创建一个新表,用于存储来路网址。例如,创建一个名为`pre_referer_log`的表:
```sql
CREATE TABLE `pre_referer_log` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`referer` varchar(255) NOT NULL DEFAULT '',
`dateline` int(10) unsigned NOT NULL DEFAULT '0',
PRIMARY KEY (`id`),
KEY `dateline` (`dateline`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
```
> **注意**:`pre_`前缀应与你的Discuz!安装前缀一致。
2. **记录来路网址**
在访问者每次访问页面时,将`HTTP_REFERER`插入到`pre_referer_log`表中。为了避免表过大,可以限制记录的数量,例如只保留最近的100条记录。
在Discuz!的模板文件(如`forumdisplay.htm`或其他适合的位置)中添加以下代码:
```php
<?php
// 确保在Discuz!的公共函数加载后执行
if(!defined('IN_DISCUZ')) {
exit('Access Denied');
}
$referer = isset($_SERVER['HTTP_REFERER']) ? daddslashes($_SERVER['HTTP_REFERER']) : '';
if(!empty($referer)) {
// 检查是否已经存在相同的来路(可选)
$count = C::t('referer_log')->count_by_referer($referer);
if($count == 0) {
// 插入新记录
C::t('referer_log')->insert(array(
'referer' => $referer,
'dateline' => $_G['timestamp']
), false, true);
// 限制记录数量,例如最多保留100条
C::t('referer_log')->query("DELETE FROM ".DB::table('referer_log')." WHERE id NOT IN (SELECT id FROM ".DB::table('referer_log')." ORDER BY dateline DESC LIMIT 100)");
}
}
?>
```
> **注意**:
> - `C::t('referer_log')` 假设你已经创建了一个数据表模型。如果没有,需要先在Discuz!的插件或自定义模块中定义该模型。
> - 上述代码中的`count_by_referer`和插入逻辑需要根据实际情况调整,或者通过其他方式确保不重复插入相同的来路网址。
#### b. 显示最近三条来路网址
在需要显示来路网址的模板文件中(如页脚或其他适当位置),添加以下代码:
```php
<?php
// 确保在Discuz!的公共函数加载后执行
if(!defined('IN_DISCUZ')) {
exit('Access Denied');
}
// 查询最近三条来路网址
$recent_referers = C::t('referer_log')->fetch_all_by_order('dateline DESC', 0, 3);
if(!empty($recent_referers)) {
echo '<div class="recent-referers">';
echo '<h3>最近访问来源:</h3>';
echo '<ul>';
foreach($recent_referers as $referer) {
// 对URL进行解码并显示
$decoded_referer = dhtmlspecialchars(urldecode($referer['referer']));
echo '<li><a href="'.$referer['referer'].'" target="_blank">'.$decoded_referer.'</a></li>';
}
echo '</ul>';
echo '</div>';
} else {
echo '<div class="recent-referers">';
echo '<p>暂无访问来源记录。</p>';
echo '</div>';
}
?>
```
> **注意**:
> - `C::t('referer_log')->fetch_all_by_order('dateline DESC', 0, 3);` 这行代码假设你已经为`referer_log`表创建了相应的数据表模型,并且支持按`dateline`排序和限制数量。如果没有,需要手动编写SQL查询,例如:
> ```php
> $recent_referers = DB::fetch_all("SELECT * FROM ".DB::table('referer_log')." ORDER BY dateline DESC LIMIT 3");
> ```
### 3. 要显示最近三条
如上所述,在显示最近来路网址的代码中,已经通过`LIMIT 3`限制了只显示最近的三条记录。确保在查询时使用类似以下的方法:
```php
// 使用数据表模型(假设已定义)
$recent_referers = C::t('referer_log')->fetch_all_by_order('dateline DESC', 0, 3);
// 或者手动编写SQL
$recent_referers = DB::fetch_all("SELECT * FROM ".DB::table('referer_log')." ORDER BY dateline DESC LIMIT 3");
```
然后在循环中遍历这3条记录并显示。
### 完整示例
假设你已经创建了`pre_referer_log`表,并且有一个数据表模型`referer_log`,以下是一个完整的实现示例:
#### a. 创建数据表模型(如果尚未创建)
在Discuz!的插件或自定义模块中,添加以下模型定义(例如在`source/plugin/your_plugin/model/referer_log_model.class.php`):
```php
<?php
if(!defined('IN_DISCUZ')) {
exit('Access Denied');
}
class table_referer_log extends discuz_table {
public function __construct() {
$this->_table = 'referer_log';
$this->_pk = 'id';
parent::__construct();
}
public function fetch_all_by_order($order = 'dateline DESC', $start = 0, $limit = 3) {
return DB::fetch_all("SELECT * FROM %t ORDER BY {$order} LIMIT {$start}, {$limit}", array($this->_table));
}
}
```
> **注意**:上述模型仅为示例,具体实现可能需要根据Discuz!的模型规范进行调整。
#### b. 记录来路网址
在适当的模板文件中(如`forumdisplay.htm`),添加以下代码:
```php
<?php
if(!defined('IN_DISCUZ')) {
exit('Access Denied');
}
$referer = isset($_SERVER['HTTP_REFERER']) ? daddslashes($_SERVER['HTTP_REFERER']) : '';
if(!empty($referer)) {
// 检查是否已存在(简单示例,实际可能需要更复杂的去重逻辑)
$exists = DB::result_first("SELECT COUNT(*) FROM ".DB::table('referer_log')." WHERE referer = %s", array($referer));
if($exists == 0) {
DB::insert('referer_log', array(
'referer' => $referer,
'dateline' => $_G['timestamp']
));
// 限制记录数量
DB::query("DELETE FROM ".DB::table('referer_log')." WHERE id NOT IN (SELECT id FROM ".DB::table('referer_log')." ORDER BY dateline DESC LIMIT 100)");
}
}
?>
```
#### c. 显示最近三条来路网址
在需要显示的位置(如页脚模板`footer.htm`),添加以下代码:
```php
<?php
if(!defined('IN_DISCUZ')) {
exit('Access Denied');
}
// 查询最近三条来路网址
$query = DB::query("SELECT * FROM ".DB::table('referer_log')." ORDER BY dateline DESC LIMIT 3");
$recent_referers = array();
while($referer = DB::fetch($query)) {
$recent_referers[] = $referer;
}
if(!empty($recent_referers)) {
echo '<div class="recent-referers">';
echo '<h3>最近访问来源:</h3>';
echo '<ul>';
foreach($recent_referers as $referer) {
$decoded_referer = dhtmlspecialchars(urldecode($referer['referer']));
echo '<li><a href="'.$referer['referer'].'" target="_blank">'.$decoded_referer.'</a></li>';
}
echo '</ul>';
echo '</div>';
} else {
echo '<div class="recent-referers">';
echo '<p>暂无访问来源记录。</p>';
echo '</div>';
}
?>
```
### 注意事项
1. **性能考虑**:频繁的数据库插入和删除操作可能影响性能,尤其是在高访问量的论坛上。可以考虑使用缓存机制,定期批量处理记录,或者限制插入频率(如每分钟只记录一次)。
2. **数据清理**:定期清理旧的记录,避免表过大影响性能。可以在插件中添加定时任务,定期执行清理操作。
3. **安全性**:确保对`HTTP_REFERER`进行适当的过滤和转义,防止XSS攻击。上述代码中使用了`dhtmlspecialchars`和`urldecode`进行处理。
4. **隐私问题**:记录用户的来路网址可能涉及隐私问题,确保遵守相关法律法规,并在必要时告知用户。
### 总结
通过以上步骤,你可以在Discuz!论坛中实现记录并显示访问者最近三个来路网址的功能。这涉及到获取`HTTP_REFERER`、将其存储到数据库,并在模板中进行展示。务必注意性能优化和安全性,以确保功能的稳定性和用户数据的安全。
他们看过
-
time
-
996素材网996n2.com
-
青提
-
zo
-
Vibe