广告体系

目前很多论坛的盈利模式主要还是广告, 因此了解清楚phpwind系统的广告体系至关重要, 本文档的目的就是介绍广告系统的使用方法, 并针对广告体系的二次开发做简单的引导. phpwind深知广告对站长的重要性, 因此在广告这一块下了很多功夫, 目的就是为了让广告体系简单易用.

进入后台, 顶部导航点击运营, 左侧导航里面第一条就是广告管理, 可见其运营的重要性. 点击广告管理就进入了强大的广告系统. 可以看到上面分成4:广告管理, 广告位管理, 广告数统计, 广告到期提醒. 默认进入广告管理.

1.    广告管理

这里会展示论坛当前所有广告列表, 顶部的搜索提供了多个选项来筛选, 当广告很多时, 查找特定的广告非常有效. 下面的每个广告都能够编辑和删除, 点击广告的描述同样能进入编辑页面, 如果需要删除多个广告, 还可以批量删除, 每个广告前面都有一个复选框, 勾选多个广告后, 选中下面的删除操作, 提交就能够同时删除多个广告了. 刚进去下面是空白了, 我们需要逐个添加广告, 点击列表上方的添加广告按钮进入添加页面. 每个选项都有说明, 这里再补充一些细节:

   表现方式有4, 每类的必填选项不一致, 但为了方便管理, 推荐每个选项都填上相应的信息, 特别是广告描述.

   链接必须以http:// 开头, 要不然会导致错误.

   选择广告位部分, 下拉框里有很多位置, 每选择一个都会相应地给出位置描述和建议, 还有更多的细节选项, 请仔细设置. 位置列表里面默认选中所有模式, 所有页面, 所有版块, 如果要变换, 可以单独选择某项或者用ctrlshift选择多项.

   某个广告暂时不用的时候可以关闭, 不一定非要删除, 方便以后有需要再开启

   广告有效时间默认1, 默认全时段暂时, 可以设置详细展示时间, 按日期和按星期可以同时有效.

   横向选择广告位实际上是一次添加多个广告, 当你选择多个广告位添加成功后在列表可以看到每个相应的广告位都多出来一个广告. 有些广告位不推荐使用横向选择方式, 比如弹窗广告, 还需要设置弹窗的参数.

 

2.    广告位管理

phpwind自带有23个广告位, 如果对这自带的23个位置不熟悉, 可以自己添加广告试试, 选择不同的广告位, 这样不仅能了解广告位的位置, 还能弄清楚各个广告位配置上的不同, 方便以后运营广告. 这自带的23个广告位几乎能满足站长运营广告的需求, 但是我们还是个站长提供了增加/删除广告位以及编辑自带广告位的功能. 另外, 广告位列表还可以选择多个广告位进行开启/关闭/删除操作. 但是自带的23个广告位不能删除,  下面补充介绍下新增广告位的功能:

   添加广告位需要有一定的代码基础, 如果不熟练请不要在正式站上操作, 防止网页出错.

   底部有广告位代码调用说明, 新添加的广告位需要将调用代码添加到相应的模板中,才能使广告位生效.调用代码如下:
 '
标识符'为必选参数,方括号中的参数为可选: '[版块ID]','[楼层数]' 
 $htmlAdvert 
为当前显示的广告内容,$arrayAdvert 为多广告内容数组

这段话的意思是, 根据自身的需求添加好广告位后, 还需要去改相应的模板代码, 后面会有案例.

 

3.    广告数统计

这里展示了所以广告位的使用情况, 很直观, 点击某个广告位就能进入该广告位上设置的广告列表, 点击后面的开启关闭数还能进行筛选, 但是要主要, 这里不会显示广告位的开启关闭状态, 要查看广告位的开启状态请到广告位管理.

 

4.    广告到期提醒

广告到期提醒默认开启, 可以设置广告到期前几天通过站内信或邮件通知广告创始人. 一般是站长本人.

 

phpwind的广告系统做的非常简单易用, 唯一有点难度的是添加广告位, 下面举例示范, 比如我们希望在快速回复输入框上面加一个广告位. 下面是操作方法:

1.       先添加好广告位

在添加广告位页面, 名称里面输入快速回复[]

标识符可以自己写, 也可以用后面提供的几种, 但必须是唯一的标识符, 不能和已有的标识符冲突, 我们这里填写FastPost, 如果采用系统提供的, 广告位的细节设置会有所不同.

消息描述, 填写帖子阅读页快速回复上面

广告显示方式, 选择显示全部

是否开启选开启

提交

这样广告位在数据库就有记录了, 但是在模板里面根本没影, 所以下一步要去修改模板

 

2.       把广告位代码复制到相应的模板

首先我们找到帖子阅读页的模板, 也就是template/wind/read.htm(默认wind风格), 找到快速回复输入框的代码, 把添加好后的广告位底部的代码复制到它的上面(需要重新点编辑添加的广告位). 但是请注意, 复制出来的代码是自动生成的, 不一定就是合理的, 需要仔细看说明.

<!--

EOT;

list($htmlAdvert,$arrayAdvert) = pwAdvert('FastPost', $fid);

if($htmlAdvert){print <<<EOT

-->

$htmlAdvert

<!--

EOT;

}

$fastpost && require_once PrintEot($fastpost);

if ($ifmagic) {

    $tmpReferer = urlencode($pwServer['HTTP_REFERER']);

print <<<EOT

-->

黄色背景部分就是添加的广告位代码, 当然$htmlAdvert变量生成的html代码只是很简单的罗列各个连接, 没有样式可言, 如果要用到样式, 可以采用$arrayAdvert变量自己写, 例如下面

<!--

EOT;

list($htmlAdvert,$arrayAdvert) = pwAdvert('FastPost', $fid);

if ($htmlAdvert) {print <<<EOT

-->

<div class="textMes">

    <table width="100%" cellspacing="0" cellpadding="0">

<!--

EOT;

    $tmpCount=0;

    $idp = 100/$db_txtadnum;

    foreach ($arrayAdvert as $value) {

       if ($tmpCount == 0) {

print <<<EOT

-->

       <tr class="tr3">

<!--

EOT;

       }

       $tmpCount++;

print <<<EOT

-->

           <td class="f_one black tac" width="$idp%">$value</td>

<!--

EOT;

       if ($tmpCount == $db_txtadnum) {

           $tmpCount=0;

print <<<EOT

-->

       </tr>

<!--

EOT;

       }

    }

    if ($tmpCount && $id < $db_txtadnum) {

       for ($i=$tmpCount;$i<$db_txtadnum;$i++) {

print <<<EOT

-->

           <td class="f_one" width="$idp%">&nbsp;</td>

<!--

EOT;

       }

print <<<EOT

-->

       </tr>

<!--

EOT;

    }

print <<<EOT

-->

    </table>

</div>

<!--

EOT;

}

$fastpost && require_once PrintEot($fastpost);

if ($ifmagic) {

    $tmpReferer = urlencode($pwServer['HTTP_REFERER']);

print <<<EOT

-->

 

3.       添加广告试试

经过上面的步骤后, 广告位就添加好了, 接下来可以添加广告试试, 这里就没有什么特殊了, 只不过在选择广告位的时候可以选择自己添加的广告位, 选择后, 旁边的文字就是你在添加广告位是填写的简介, 下面的位置设置会根据前面标识符的填写而决定, 如果自己写的, 一般都是3, 模式, 页面, 版块, 如果写成类似Layer.xxx, 则还会多出来楼层一栏, 如果写成Mode.xxx就会根据后面的字符串来决定, 简而言之, 标识符有Mode.部分就会根据字符串其他部分精确配置详细选项, 如果没有找到类似Layer, Site, Forum这类就没有精确位置选项.

 

看过如何新增广告位以后, 再来研究下核心函数pwAdvert, 这个函数的定义在require/common.php.

/**

 * 获取广告数据

 *

 * @global int $timestamp

 * @global string $db_advertdb

 * @global string $db_mode

 * @global array $_time

 * @param string $advKey 广告key

 * @param int $fid 版块id

 * @param int $lou 楼号

 * @param string $scr

 * @return array

 */

function pwAdvert($advKey, $fid = 0, $lou = -1, $scr = 0) {

    global $timestamp, $db_advertdb, $db_mode, $_time;

    if (empty($db_advertdb[$advKey])) return false; //从这条语句可以看出, 所有的广告时间都是已经生成好并记录在缓存文件里了, 并不是实时查询数据库所得

    $hours = $_time['hours'] + 1;

    $fid || $fid = $GLOBALS['fid'];

    $scr || $scr = $GLOBALS['SCR'];

    $scr = strtolower($scr);

    $lou = (int) $lou;

    $tmpAdvert = $db_advertdb[$advKey]; //取到对应标识符的广告列表

    if ($db_advertdb['config'][$advKey] == 'rand') { //如果广告位的显示方式设置成随机选, 则打乱广告顺序

       shuffle($tmpAdvert);

    }

    $arrAdvert = array();

    $advert = '';

    foreach ($tmpAdvert as $key => $value) {

       //如果广告的显示时间段, 模式, 页面, 版块设置不符合给定的参数fid, 不显示

       if ($value['stime'] > $timestamp || $value['etime'] < $timestamp || ($value['dtime'] && strpos(",{$value['dtime']},", ",{$hours},") === false) || ($value['mode'] && strpos($value['mode'], $db_mode) === false) || ($value['page'] && (strpos($value['page'], ",$scr,") === false || ($scr == 'read' && $value['page'] == 'thread'))) || ($value['fid'] && $scr != 'index' && strpos(",{$value['fid']},", ",$fid,") === false) || ($value['lou'] && strpos(",{$value['lou']},", ",$lou,") === false)) {

           continue;

       }

       if ((!$value['ddate'] && !$value['dweek']) || ($value['ddate'] && strpos(",{$value['ddate']},", ",{$_time['day']},") !== false) || ($value['dweek'] && strpos(",{$value['dweek']},", ",{$_time['week']},") !== false)) {

           $arrAdvert[] = $value['code']; //记录所有应该显示的广告

           $advert .= is_array($value['code']) ? $value['code']['code'] : $value['code']; //将显示的广告位的html代码简单拼接, 前面讲过如果觉得这种简单拼接显示效果不好, 可以采用arrAdvert返回的数据自己写

           if ($db_advertdb['config'][$advKey] != 'all') break; //如果广告位的显示方式设置不是显示全部, 则取了一条以后就跳出循环

       }

    }

    return array($advert, $arrAdvert);

}

 

看了上面的代码, 大家一定很关心$db_advertdb这个参数那你来的, 这个参数储存在缓存文件中, data/bbscache/config.php

$db_advertdb=array(

    'config' => array(

       'FastPost' => 'all', //标识符, 以及对于展示方式

    ),

    'FastPost' => array(//标识符下的所有广告

       '109' => array(//广告对应的具体参数

           'stime' => '1329235200',

           'etime' => '1360857599',

           'code' => '<a href="http://www.test.com" target="_blank" style="color:#FF0000;font-size:12px;" >测试新增广告位</a>', //测试添加的是文字广告, 这里code就是生成的简单html代码, 可见里面包含了所有设置的参数, 链接的URL, 文字以及字体颜色, 大小

       ),

       '110' => array(

           'stime' => '1329235200',

           'etime' => '1360857599',

           'code' => '<a href="http://www.test.com" target="_blank" style="color:#008000;font-size:12px;" >测试新增广告位2</a>',

       ),

    ),

);

 

那么, 这个参数是怎么生成的呢, 这就要看广告体系的核心代码了, 位于admin/setadvert/php, 下面只截取新增广告的代码, 其他代码如果读者有兴趣可以自行研究.

elseif ($job == 'save') {

       S::gp(array('id','config','advert','lous','fids','modes','pages','ddate','dweek','dtime')); //读取广告设置参数

 

       $id = intval($id);

 

       !isset($cates[$advert['ckey']]) && $basename = "javascript:history.go(-1);" && adminmsg('advert_ckey_noexist'); //检查广告位是否存在

       //下面根据广告表现形式对参数做一些合法性判断及处理

       if ($config['type'] == 'code') {//广告表现形式是代码

           $tmpConfig = S::getGP('config');

           $config['htmlcode'] = $tmpConfig['htmlcode'];

           if (!$config['htmlcode']/* || strlen($config['htmlcode'])>1024*/) {

              $basename = "javascript:history.go(-1);";

              adminmsg('advert_code_error');

           } elseif(in_array($advert['ckey'],array('Site.FloatLeft','Site.FloatRight','Site.FloatRand')) && preg_match('/<script[^>]*?>.*?<\/script>/si',$config['htmlcode'])) {

              $basename = "javascript:history.go(-1);";

              adminmsg('advert_float_error');

           }

       } elseif ($config['type'] == 'txt') {//广告表现形式是文字

           if (!$config['title'] || !$config['link']) {

              $basename = "javascript:history.go(-1);";

              adminmsg('advert_txt_error');

           }

           $config['title'] = str_replace(array('&lt;','&gt;'),array('<','>'),$config['title']);

           $config['size'] = (int) $config['size'];

           !$config['size'] && $config['size'] = 12;

       } elseif ($config['type'] == 'img' && (!$config['url'] || !$config['link'])) {//广告表现形式是图片

           $basename = "javascript:history.go(-1);";

           adminmsg('advert_img_error');

       } elseif ($config['type'] == 'flash' && !$config['link']) {//广告表现形式是flash

           $basename = "javascript:history.go(-1);";

           adminmsg('advert_flash_error');

       }

       if($config['type'] == 'flash') {

           $config['width'] = ($config['width'] == "") ? "120" : $config['width'];

           $config['height'] = ($config['height'] == "") ? "120" : $config['height'];

       }

       if (empty($advert['descrip'])) {//检查必须输入项

           if ($config['type'] == 'code') {

              $advert['descrip'] = substrs(strip_tags($config['htmlcode']),250);

           } elseif ($config['type'] == 'txt') {

              $advert['descrip'] = substrs($config['title'],250);

           }

           empty($advert['descrip']) && $basename = "javascript:history.go(-1);" && adminmsg('advert_descrip');

       }

       $advert['stime'] = PwStrtoTime($advert['stime']);

       $advert['etime'] = PwStrtoTime($advert['etime']) + 86399;

 

       if ($advert['stime'] > $advert['etime']) {//检查有效时间是否合理

           $basename = "javascript:history.go(-1);";

           adminmsg('advert_time_error');

       }

       //对详细展示时间参数整理

       $config['ddate'] = $config['dweek'] = $config['dtime'] = '';

       if (is_array($ddate)) {

           $config['ddate'] = implode(',',$ddate);

       }

       if (is_array($dweek)) {

           $config['dweek'] = implode(',',$dweek);

       }

       if (is_array($dtime) && count($dtime)<24) {

           $config['dtime'] = implode(',',$dtime);

       }

       $advert['orderby'] = (int)$advert['orderby']; //显示顺序

       $advert['ifshow'] = $advert['ifshow'] ? 1 : 0; //广告是否开启

 

       $tmpCKey = strtolower($advert['ckey']);

       if (strpos($tmpCKey,'popup.')) {//根据广告位标识符判断是否为弹窗广告, 如果是整理弹窗细节参数

           $config['winHeight'] = $config['winHeight'] ? intval($config['winHeight']) : 100;

           $config['winWidth'] = $config['winWidth'] ? intval($config['winWidth']) : 200;

           $config['winClose'] = $config['winClose'] ? intval($config['winClose']) : 5;

       }

       if (strpos($tmpCKey,'layer.') && is_array($lous) && !in_array('-1',$lous)) {//如果有配置显示楼层, 整理楼层参数

           $config['lou'] = implode(',',$lous);

       }

 

       if (is_array($fids) && !in_array('-1',$fids)) {//整理fid参数

           $config['fid'] = implode(',',$fids);

       }

       if (is_array($pages) && !in_array('page',$pages)) {//整理显示页面参数

           $config['page'] = implode(',',$pages);

       }

       if (is_array($modes) && !in_array('mode',$modes)) {//整理显示模块参数

           $config['mode'] = implode(',',$modes);

       }

 

       //下面段代码是整理图片类型广告的参数, 包括上传图片

       if ($config['width']) {

           $config['width'] = intval($config['width']) . ($config['width'][strlen($config['width'])-1] == '%' ? '%' : '');

       }

       if ($config['height']) {

           $config['height'] = intval($config['height']) . ($config['height'][strlen($config['height'])-1] == '%' ? '%' : '');

       }

      

       //广告图片上传

       if ($config['type'] == 'img')  {

           //图片上传

           $newConfigUrl = $newConfigLink =  array();

           L::loadClass('advupload', 'upload', false);

           foreach ($config['imgupload'] as $key => $value) {

              if ($value != 0) {

                  $img = new AdvUpload($key);

                  $returnImg = PwUpload::upload($img);

                  if (!is_array($returnImg) || count($returnImg) == 0) continue;

                  $newConfigUrl[] = "$db_attachname/".$returnImg[0]['fileuploadurl'];

                  $newConfigLink[] = $config['link'][$key];

              } else {

                  $newConfigUrl[] = $config['url'][$key];

                  $newConfigLink[] = $config['link'][$key];

              }

           }

           unset($config['imgupload']);

           $config['link'] = $newConfigLink;

           $config['url'] = $newConfigUrl;

       }

 

       foreach ($config as $key => $value) {

           if ($config['type'] == 'img' && in_array($key,array('url','link'))) {

              $tmp = array();/*support multi pictures*/

              $config['multi'] = count($value);

              $index = 0;/* sort array */

              foreach($value as $k=>$v){

                  $tmp[$index] = stripslashes(str_replace(array('&#61;','&amp;'),array('=','&'),$v));

                  $index++;

              }

              if($config['multi']>1){

                  $value = $tmp;

              }else{

                  $value = $tmp[0];

              }

           }else{

              $value = stripslashes(str_replace(array('&#61;','&amp;'),array('=','&'),$value));/*other*/

           }

           $config[$key] = is_array($value) ? $value:$value;

      

       }

       $config['size'] = $config['size']."px";

        $config = addslashes(serialize($config)); //系列化广告参数方便入库

      

       if ($id) {//如果有传id, 说明是编辑已有广告, update数组

           $db->update("UPDATE pw_advert SET " . S::sqlSingle(array(

              'ckey'     => $advert['ckey'],

              'stime'       => $advert['stime'],

              'etime'       => $advert['etime'],

              'ifshow'   => $advert['ifshow'],

              'orderby'  => $advert['orderby'],

              'descrip'  => $advert['descrip'],

              'config'   => $config

           )) . " WHERE type='1' AND id=".S::sqlEscape($id));

       } else {//否则插入新广告数据

           $otherkey = (array)S::getGP('otherkey');

           $userService = L::loadClass('UserService', 'user'); /* @var $userService PW_UserService */

           $winduid = $userService->getUserIdByUserName($admin_name);

           foreach ($otherkey as $value) {//横向选择的广告位逐条插入数据

              if (!$cates[$value] || $advert['ckey'] == $value) continue;

              $db->update("INSERT INTO pw_advert SET " . S::sqlSingle(array(

                  'uid'       => $winduid,

                  'type'     => 1,

                  'ckey'     => $value,

                  'stime'       => $advert['stime'],

                  'etime'       => $advert['etime'],

                  'ifshow'   => $advert['ifshow'],

                  'orderby'  => $advert['orderby'],

                  'descrip'  => $advert['descrip'],

                  'config'   => $config

              )));

           }

           //原本广告位插入的广告数据入库

           $db->update("INSERT INTO pw_advert SET " . S::sqlSingle(array(

              'uid'       => $winduid,

              'type'     => 1,

              'ckey'     => $advert['ckey'],

              'stime'       => $advert['stime'],

              'etime'       => $advert['etime'],

              'ifshow'   => $advert['ifshow'],

              'orderby'  => $advert['orderby'],

              'descrip'  => $advert['descrip'],

              'config'   => $config

           )));

           $id = $db->insert_id();

       }

       if ($advert['ifshow']) {

           $db->update("UPDATE pw_advert SET ifshow=1 WHERE type=0 AND ifshow=0 AND ckey=".S::sqlEscape($advert['ckey']));

       }

       updatecache_c();//更新文件缓存

       adminmsg('operate_success',"$basename");//操作成功

    }

       至于更新文件缓存的方法updatecache_c, 有兴趣的读者可以自行研究, 位于admin/cache.php文件里. 最后列出和广告系统相关的数据表.

1.       -- TableName pw_advert 系统广告信息
-- Fields id
广告ID
-- Fields type
广告类型
-- Fields uid
用户ID
-- Fields ckey
广告位标识符
-- Fields stime
开始时间
-- Fields etime
结束时间
-- Fields ifshow
是否启用
-- Fields orderby
排序
-- Fields descrip
广告位描述
-- Fields config
广告内容具体设置

2.       -- TableName pw_buyadvert 广告出租信息 (目前没用到)
-- Fields id
出租信息id
-- Fields uid
申请用户的ID
-- Fields ifcheck
是否启用
-- Fields lasttime
持续时间
-- Fields config
申请的信息