帝国CMS新闻模型付费阅读实现:前段免费后段隐藏且不改核心文件 📅 发布时间:2026/9/14 2:59:37 👁 浏览次数: 简介帝国CMS的新闻模型部分内容隐藏付费查看插件专为使用帝国CMS构建新闻资讯类网站的管理员与二次开发者设计解决文章正文局部付费解锁、会员免费阅读等增值运营需求。压缩包共20个文件总大小132KB内部包含安装说明文档、输入表单替换HTML代码、后台SQL执行脚本以及PHP模板、JavaScript、CSS样式、GIF/PNG图片等文件类型结构清晰便于按功能定位修改。已有444人学习下载。该插件支持管理员自由隐藏新闻内容任意片段按会员组配置免费查看权限并通过支付解锁完整内容帮助网站实现内容分级和会员激励。文档对数据库表结构变更、表单代码替换位置和后台SQL执行步骤均有说明方便开发者直接部署或二次定制插件目录中PHP与JS文件配合实现前端交互逻辑CSS与图片资源则用于控制隐藏内容展示样式整体可作为帝国CMS内容变现的完整参考方案适合需要提升内容价值、增强用户黏性的站点运营者。1. 帝国CMS新闻模型付费阅读不碰核心文件的隐藏方案很多做资讯站的站长都有同一个矛盾文章全文公开广告收入抵不过内容被采集直接一刀切全部付费又留不住新访客。帝国CMS的新闻模型本身就是文章类内容的标准结构但后台并没有“正文部分隐藏”的官方开关。这篇博客要讲的是只靠帝国CMS现有字段、模板标签和几个PHP函数实现“前几段免费、剩余内容付费”的完整做法并且能单独设置哪一级别的会员免费看。整个过程不修改任何数据库表结构不需要熟悉整套商城插件学会之后可以复用到专题、图集模型上。2. 帝国CMS新闻模型的字段扩展与分段原理2.1 为什么不用新增字段而用正文标记最直接的想法是给新闻模型增加一个“付费内容”字段比如后台多一个textarea。但这个方案有三个明显问题编辑要分两次填写正文复制内容时容易漏段后台列表页和搜索页如果统揽所有字段额外字段会增加查询压力很多站点的新闻内容是采集或一键导入的原有数据都在newstext字段里临时拆到新字段非常麻烦。所以常见做法是继续使用newstext保存完整正文在需要隐藏的段落前后加上自定义标记[payhide]和[/payhide]。前台模板收到正文后用正则把[payhide]包住的片段切出来再根据当前用户的登录状态、会员等级和购买记录决定是否输出这一片段。这样编辑还是在同一个框里写文章只是多两个标记哪怕以后不付费了直接把标记删掉即可。2.2 自定义标记的权限层级设计付费查看不是简单的“全看”或“全不看”需要区分四个状态。下面这张表是我们常见的权限设计用户状态免费段落隐藏段落提示内容未登录显示不显示请登录后购买或升级会员普通会员等级低于免费阈值显示不显示显示积分价格点击购买VIP会员等级达到免费阈值显示显示无提示直接全文输出已购买用户显示显示无提示直接全文输出管理员只需要在后台设置一个“免费查看的最低会员等级”参数比如设为VIP等级ID为3那么等级ID小于等于3的会员都能免费看全篇等级ID大于3的会员需要消耗站内积分或充值购买。购买成功后往独立的记录表写入一条数据下次访问直接放行。这套设计的好处是会员体系不需要改动只需要读取帝国CMS自带的groupid字段购买记录也和会员表、内容表分离不影响帝国CMS原生的管理功能。2.3 正则解析与多个隐藏块的处理在PHP中切割[payhide]片段我一般用下面这段正则$pattern /\[payhide\](.*?)\[\/payhide\]/s;(.*?)是非贪婪匹配s修饰符让点号能匹配换行。这样即使隐藏段落在正文中间、跨了多行都能正确匹配。如果一篇文章里有多个隐藏块还可以把逻辑改写成preg_replace_callback在回调里统一判断权限而不是只取第一个匹配结果。需要说明的是帝国CMS后台的富文本编辑器默认会把[符号转成HTML实体。操作时要提示编辑在“源代码”模式输入[payhide]或者在编辑器的过滤配置里加白名单。否则正则可能匹配不到。3. 用 PHP 帝国CMS模板标签实现付费隐藏的完整代码3.1 后台允许模板嵌入 PHP 代码帝国CMS为了安全默认情况下模板中的?php代码会被过滤。需要进入后台的“系统设置 → 参数设置 → 核心设置”找到“模板是否允许PHP代码”把它设为“是”然后保存并更新缓存。这一步不做后面所有模板代码都不会执行。开启后在新闻内容页模板里可以直接使用?php ?块。帝国CMS会先解析[!--字段名--]标签再把剩余PHP输出。所以我们要把原来放[!--newstext--]的地方替换成一段PHP代码让最终输出的内容是处理后的HTML。3.2 新闻内容页模板中的核心判断代码以下是一段可以直接放在内容页模板中的PHP代码替换[!--newstext--]的位置。假设你的帝国CMS表前缀为phome_如果不是请自行替换。?php global $db, $public_r, $navinfor; $userid (int)getcvar(mluserid); $user_r array(); $is_free_level 0; // 是否达到免费查看等级 $is_paid 0; // 是否已购买过本文 $content $navinfor[newstext]; $free_content $content; $pay_content ; // 1. 用正则把隐藏块切出来 $pattern /\[payhide\](.*?)\[\/payhide\]/s; if(preg_match($pattern, $content, $matches)) { $pay_content $matches[1]; $free_content preg_replace($pattern, , $content); } if($userid) { // 2. 读取当前登录用户 $user_r $db-fetch1(select * from phome_enewsuser where userid$userid); $usergid intval($user_r[groupid]); // 3. 后台参数pay_free_level 是免费查看的最低等级ID $free_level intval($public_r[pay_free_level]); if($free_level 0 $usergid 0 $usergid $free_level) { $is_free_level 1; } // 4. 检查是否已经购买过 $paycheck $db-fetch1(select id from phome_pay_record where classid{$navinfor[classid]} and id{$navinfor[id]} and userid$userid order by id desc limit 1); if($paycheck[id]) { $is_paid 1; } } // 5. 输出免费部分 echo $free_content; // 6. 根据权限输出隐藏部分或提示 if($pay_content) { if($is_free_level || $is_paid) { echo $pay_content; } else { echo div styleborder:1px solid #e5e5e5;padding:15px;margin:10px 0; 隐藏内容需要付费或升级会员查看。br / a href/e/member/login/登录/a a href/e/action/buypay.php onclickreturn false;立即购买/a /div; } } ?这段代码的执行逻辑分四步先用正则切割隐藏片段再判断用户是否登录登录后读取其会员等级然后从自定义购买记录表里查是否买过最后按权限拼接输出。$public_r是帝国CMS后台的参数组pay_free_level和后面要用的pay_price都是通过后台自定义参数存进去的不修改任何源文件就能读取。3.3 购买记录表与支付扣费脚本上面代码依赖一张记录购买行为的表。推荐用下面SQL建表CREATE TABLE phome_pay_record ( id int(11) NOT NULL AUTO_INCREMENT, classid int(11) NOT NULL DEFAULT 0, id int(11) NOT NULL DEFAULT 0, userid int(11) NOT NULL DEFAULT 0, price int(10) NOT NULL DEFAULT 0, paytime int(10) NOT NULL DEFAULT 0, PRIMARY KEY (id), KEY userid (userid), KEY id (id) ) ENGINEMyISAM DEFAULT CHARSETutf8;字段说明classid是新闻所属栏目IDid是文章IDuserid是购买用户IDprice记录扣了多少积分paytime是购买时间戳。联合查询时一直用classid id userid所以后面两个索引很有必要。扣费脚本可以放在/e/action/buypay.php接收classid和id两个POST参数。核心逻辑如下?php require(../class/connect.php); require(../class/db_sql.php); require(../class/config.php); require(../member/class/user.php); $link db_connect(); $empire new mysqlquery(); $dbtbpre $ecms_config[db][dbtbpre]; $userid (int)getcvar(mluserid); if(empty($userid)) { echo 请先登录; exit; } $classid (int)$_POST[classid]; $id (int)$_POST[id]; if(empty($classid) || empty($id)) { echo 参数错误; exit; } // 读取后台设置的积分价格 $public_r $empire-fetch1(select * from {$dbtbpre}enewspublic limit 1); $price intval($public_r[pay_price]); if($price 0) { echo 价格配置错误; exit; } // 检查是否已经购买过防止重复扣费 $check $empire-fetch1(select id from {$dbtbpre}pay_record where classid$classid and id$id and userid$userid limit 1); if($check[id]) { echo 已经购买过; exit; } // 扣除用户积分前提是phome_enewsuser有money字段 $user $empire-fetch1(select money from {$dbtbpre}enewsuser where userid$userid); if($user[money] $price) { echo 积分不足; exit; } $empire-query(update {$dbtbpre}enewsuser set moneymoney-$price where userid$userid); $empire-query(insert into {$dbtbpre}pay_record (classid,id,userid,price,paytime) values ($classid,$id,$userid,$price,.time().)); echo success; exit; ?这里做了三件事检查登录状态、检查是否重复购买、扣除积分并写入记录。{$dbtbpre}enewspublic是帝国CMS存系统参数的表pay_price这个自定义参数会自动出现在里面。注意有些帝国CMS安装时money字段可能叫user_money或者qf需要以自己站点的会员字段为准。4. 会员免费查看与积分付费的实战配置4.1 设置积分价格和免费会员等级在帝国CMS后台“系统设置 → 参数设置”中添加两个自定义变量变量名类型含义示例值pay_price数字查看隐藏部分需要的积分30pay_free_level数字达到此等级ID及以下的会员可免费看3pay_show_tips文本未付费时显示的提示文字请购买或升级VIPpay_free_level的取值要和后台“会员管理 → 会员等级”里的等级ID对应。帝国CMS的等级ID通常是数字越小权限越高比如1是管理员、3是VIP会员、5是普通会员。如果你想让VIP免费看就把pay_free_level填成VIP对应的ID。判断时用usergid free_level所以等级ID为4、5的普通会员不会免费。添加完成后需要更新帝国CMS的系统缓存让$public_r里出现这几个变量。可以直接在后台点“更新缓存”也可以进入/e/admin/后刷新。4.2 购买跳转和ReturnUrl的处理前面的模板代码中“立即购买”按钮只是在页面上显示一个链接实际使用时需要向/e/action/buypay.php提交表单。要避免购买后跳转到首页最稳妥的办法是在表单里携带当前页面地址form methodpost action/e/action/buypay.php input typehidden nameclassid value?php echo $navinfor[classid]; ? / input typehidden nameid value?php echo $navinfor[id]; ? / input typehidden namereturnurl value?php echo htmlspecialchars($_SERVER[REQUEST_URI]); ? / button typesubmit使用30积分查看隐藏内容/button /form在buypay.php最后扣费成功后可以加一段header(Location: .$_POST[returnurl]);exit;。如果站点开启了伪静态REQUEST_URI已经经过Rewrite跳转会保留当前文章的伪静态URL不会因为参数丢失导致浏览器提示“请重新提交表单”。如果你正在调试帝国CMS的伪静态规则尤其要注意buypay.php这个入口不要被Rewirte成文章详情页否则内部跳转会失效。4.3 常见配置错误与排查方向模板代码写好之后90%的问题出在这几个地方模板缓存不更新帝国CMS会缓存编译后的模板修改模板文件后必须到后台“系统设置 → 数据更新”中刷新模板缓存否则代码不生效。$public_r里没有自定义参数参数设置中添加后记得更新系统缓存并检查变量名是否和代码一致。getcvar(mluserid)返回空页面需要引入帝国CMS的/class/connect.php和/member/class/user.php内容页模板已经引入所以多数不会出现。如果专门写独立脚本必须require。正则匹配不到先查看数据库里newstext字段保存的源文本是不是[payhide]很多编辑器会把方括号转成#91;。可以直接在PHP里echo $content;查看原始输出。会员等级判断错误用echo $usergid;打印当前用户的等级ID确认后台设置的等级ID是否和数据库中一致。表前缀不一致所有phome_开头的表名都要改成你站点实际的前缀帝国CMS安装时可以自定义不一定都是phome_。5. 从验证到提效付费隐藏功能的自测清单与性能优化5.1 四组测试用例功能上线前按下面的顺序过一遍场景预期结果未登录访问文章页看到免费段落和登录提示没有隐藏内容普通会员访问看到免费段落和“购买”按钮点击后能跳转扣费达到免费等级的会员访问看到全文没有提示普通会员购买后再次访问看到全文不会重复扣积分测试时还要检查购买记录表里是否多了一行数据并且用户积分被扣了一次。5.2 消除重复查询用静态变量缓存购买状态内容页模板里如果存在多个隐藏块每段都会执行一次查询购买记录的SQL。可以在代码顶部加一个当前页级别的缓存变量static $pay_cache array(); $cache_key $navinfor[classid] . _ . $navinfor[id]; if(!isset($pay_cache[$cache_key])) { $pay_cache[$cache_key] $is_paid; } else { $is_paid $pay_cache[$cache_key]; }这样同一个页面内的多个隐藏块共享同一个购买记录查询结果避免无谓的数据库压力。对文章浏览量大的站点还可以把这层判断写进帝国CMS的自定义函数库/e/class/hdtfun.php里通过模板标签调用方便多个模板复用。5.3 与帝国CMS生成sitemap的收录策略最后一个容易被忽略的细节付费隐藏内容在页面源代码中不会输出所以搜索引擎抓取到的只是免费部分。这反而是一件好事能有效防止大量内容被采集后全文转载。如果你用帝国CMS自带的sitemap插件或自己循环生成sitemap只需要照常提交新闻URL不需要为付费内容单独建钩子。但要注意千万不能把那几个$is_paid、$is_free_level的判断结果放进缓存。有些站点用帝国CMS的静态化插件把详情页生成纯HTML一旦管理员在生成时是登录状态缓存页面就会带着付费内容写入HTML文件之后所有访客都能看到隐藏部分。解决方案是对启用了付费隐藏的文章在内容模板中禁用动态缓存或者把付费判断放在动态PHP区域不要依赖静态页。这个问题不解决后面会员免费查看和积分付费都会失效。本文还有配套的精品资源点击获取