Backlinks.com 是目前使用人数最多、最容易上手和使用的网页文字链接交易平台。

Discuz! X 系列作为国内使用最广泛的论坛门户建站软件,其中 Backlinks.com 的用户也不少。但是,也正是因为 Discuz! 强大的模板机制,直接导致了我们难以便捷地向 Discuz! 的站点页面中添加我们需要的 PHP 代码,甚至只是 JavaScript。

本文将向大家详细介绍如何利用 Discuz! 自带的模板 Hook(钩子)功能向各页面添加自定义代码(PHP、JavaScript 均可)。

此方法是基于 Discuz! 的插件功能来实现的,整个过程不修改 Discuz! 核心代码,方便易用。

Step 1: 制作自定义代码插件

编写文件 install.phpuninstall.phpvalidator.xmldiscuz_plugin_backlinks.xmlbacklinks.class.php。内容分别如下:

install.php 文件内容

<?php $finish = true; ?>

uninstall.php 文件内容

<?php $finish = true; ?>

validator.xml 文件内容

<?xml version="1.0" encoding="UTF-8"?>
<root>
    <item id="Title"><![CDATA[Discuz! Plugin Validator]]></item>
    <item id="Version"><![CDATA[X2]]></item>
    <item id="Data">
        <item id="0"><![CDATA[source/plugin/backlinks/backlinks.class.php]]></item>
    </item>
</root>

discuz_plugin_backlinks.xml 文件内容

<?xml version="1.0" encoding="UTF-8"?>
<root>
    <item id="Title"><![CDATA[Discuz! Plugin]]></item>
    <item id="Version"><![CDATA[X2]]></item>
    <item id="Data">
        <item id="plugin">
            <item id="available"><![CDATA[1]]></item>
            <item id="adminid"><![CDATA[1]]></item>
            <item id="name"><![CDATA[Backlinks.com Code Installation]]></item>
            <item id="identifier"><![CDATA[backlinks]]></item>
            <item id="description"><![CDATA[( N/A )]]></item>
            <item id="datatables"><![CDATA[]]></item>
            <item id="directory"><![CDATA[backlinks/]]></item>
            <item id="copyright"><![CDATA[YChong.com]]></item>
            <item id="version"><![CDATA[1.0]]></item>
            <item id="__modules">
                <item id="0">
                    <item id="name"><![CDATA[backlinks]]></item>
                    <item id="menu"><![CDATA[]]></item>
                    <item id="url"><![CDATA[]]></item>
                    <item id="type"><![CDATA[11]]></item>
                    <item id="adminid"><![CDATA[0]]></item>
                    <item id="displayorder"><![CDATA[0]]></item>
                    <item id="navtitle"><![CDATA[]]></item>
                    <item id="navicon"><![CDATA[]]></item>
                    <item id="navsubname"><![CDATA[]]></item>
                    <item id="navsuburl"><![CDATA[]]></item>
                </item>
            </item>
        </item>
        <item id="version"><![CDATA[X2]]></item>
        <item id="installfile"><![CDATA[install.php]]></item>
        <item id="uninstallfile"><![CDATA[uninstall.php]]></item>
        <item id="var">
        </item>
    </item>
</root>

backlinks.class.php 文件内容

<?php

class plugin_backlinks_forum extends plugin_backlinks {
    function index_side_bottom_output() {
        $output = '';
        $output .= '<div id="portal_block_74" class="block move-span"><div style="background-image: url(static/image/common/title.png); background-repeat: repeat;" class="blocktitle title"><span class="titletext" style="margin-left: 10px; font-size: 12px;">友情链接</span></div><div id="portal_block_74_content" class="dxb_bc"><div class="module cl ml mls">';

// ===== Backlinks.com 代码 (修改后)开始 =====

// THE FOLLOWING BLOCK IS USED TO RETRIEVE AND DISPLAY LINK INFORMATION.
// PLACE THIS ENTIRE BLOCK IN THE AREA YOU WANT THE DATA TO BE DISPLAYED.

// MODIFY THE VARIABLES BELOW:
// The following variable defines whether links are opened in a new window
// (1 = Yes, 0 = No)
$OpenInNewWindow = "1";

// # DO NOT MODIFY ANYTHING ELSE BELOW THIS LINE!
// ----------------------------------------------
$BLKey = "";

if ( strlen( $_SERVER['SCRIPT_URI'] ) ) {
    $_SERVER['REQUEST_URI'] = $_SERVER['SCRIPT_URI'] . ( ( strlen( $_SERVER['QUERY_STRING'] ) ) ? '?' . $_SERVER['QUERY_STRING'] : '' );
}

if ( !strlen( $_SERVER['REQUEST_URI'] ) ) {
    $_SERVER['REQUEST_URI'] = $_SERVER['SCRIPT_NAME'] . ( ( strlen( $_SERVER['QUERY_STRING'] ) ) ? '?' . $_SERVER['QUERY_STRING'] : '' );
}

$QueryString  = "LinkUrl=" . urlencode( ( ( $_SERVER['HTTPS'] == 'on' ) ? 'https://' : 'http://' ) . $_SERVER['HTTP_HOST'] . $_SERVER['REQUEST_URI'] );
$QueryString .= "&Key=" . urlencode( $BLKey );
$QueryString .= "&OpenInNewWindow=" . urlencode( $OpenInNewWindow );

//if ( intval( get_cfg_var( 'allow_url_fopen' ) ) && function_exists( 'readfile' ) ) {
//  @readfile( "http://www.backlinks.com/engine.php?".$QueryString );
//}
//elseif ( intval( get_cfg_var( 'allow_url_fopen' ) ) && function_exists( 'file' ) ) {
if ( intval( get_cfg_var( 'allow_url_fopen' ) ) && function_exists( 'file' ) ) {
    if ( $content = @file( "http://www.backlinks.com/engine.php?".$QueryString ) )
        $output .= @join( '', $content );
} elseif ( function_exists( 'curl_init' ) ) {
    $ch = curl_init( "http://www.backlinks.com/engine.php?" . $QueryString );
    curl_setopt( $ch, CURLOPT_HEADER, 0 );
    curl_exec( $ch );
    if ( curl_error( $ch ) )
        $output .= "Error processing request";
    curl_close( $ch );
} else {
    $output .= "It appears that your web host has disabled all functions for handling remote pages and as a result the BackLinks software will not function on your web page. Please contact your web host for more information.";
}

// ===== Backlinks.com 代码 (修改后)结束 =====

        $output .= '</div></div></div>';
        return $output;
    }
}

?>

此处解释一下 Backlinks.com 提供的 PHP 代码结构。这段代码通过将唯一的识别码 $BLKey 以及当前页面 URL 等信息传送到 Backlinks.com,返回内容后直接显示在当前区域。代码共用了三个判断来兼容各种环境,这三个函数都是用来请求远程 HTTP 数据的。第一个是 readfile 函数,它取得参数中 URL 返回的数据后,直接打印在当前 HTML 位置,而不是输出到返回值(返回值是内容的长度);第二个是 file 函数,它返回的是一个将参数 URL 返回的数据以行分割的数组;第三个是 curl 系列函数,除非前面有 curl_setopt($ch, CUROPT_RETURNTRANSFER,1); ,否则该函数将直接在当前 HTML 位置打印返回的数据。

类中函数 index_side_bottom_output() 的意义是,捕捉模板中名为 index_side_bottom 的“钩子”,并在此“钩子”所在的位置执行函数 index_side_bottom_output()。我们也正是利用这一途径,将 Backlinks.com 的返回代码输出到页面中。

Step 2: 修改 Backlinks.com 提供的 PHP 代码

为了使程序依照我们的期望,在固定的模板 Hook 中显示返回的数据内容,我们需要修改 Backlinks.com 提供的 PHP 代码,使之将返回的数据内容写入 Hook 回调函数的返回值中,而不是直接在当前 HTML 输出位置打印数据内容。

找到代码片段的中部:

if ( intval( get_cfg_var( 'allow_url_fopen' ) ) && function_exists( 'readfile' ) ) {
    @readfile( "http://www.backlinks.com/engine.php?".$QueryString );
} elseif ( intval( get_cfg_var( 'allow_url_fopen' ) ) && function_exists( 'file' ) ) {

修改为:

if ( intval( get_cfg_var( 'allow_url_fopen' ) ) && function_exists( 'file') ) {

此处修改的含义为:去除对第一个函数 readfile 的判断(因为 readfile 函数不论如何都会直接打印返回的数据,而不能写入到某变量中),使之直接判断 file 函数和 curl 系列函数。

然后,将代码片段中的所有 print 替换为 $output .= ,意为将返回的数据内容追加到变量 $output 中(结尾直接将变量 $output 作为返回值返回给 Hook 回调函数)。

Step 3: 安装、激活插件

将上述的四个文件上传到 /source/plugin/backlinks 目录中,进入 Discuz! X 管理后台,点选安装新插件 Backlinks.com Code Installation 1.0。

Discuz! X 中自定义 PHP 代码 (Backlinks.com) 添加方法

Discuz! X 中自定义 PHP 代码 (Backlinks.com) 添加方法

完成后更新缓存,进入站点首页即可看到效果。

本文附件