Please enable Javascript to view the contents

phpcms如何实现在含有子栏目的栏目下添加内容

 ·  ☕ 8 分钟

对于题目的解释:

假设现在有一个一级栏目 为:栏目1

其下有二级栏目 :栏目1=>栏目11,栏目1=>栏目12,栏目1=>栏目13

同时栏目1下有文章列表 : 栏目1—–文章1,栏目1—–文章2,栏目1—–文章3,栏目1—–文章4

本篇博文大部分转自于

http://blog.csdn.net/yanhui_wei/article/details/8007569 首先感谢分享

本人抄写本篇博客的目的是为补充和以后的一些这样改动后的bug

一、phpcms-v9默认情况下只能在最底层栏目下添加内容,而不能给含有子栏目的栏目添加内容,如果需要给含有子栏目的栏目下添加内容的需求,则需要修改content.php控制器的如下代码:

修改public function public_categorys() 方法

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
/**
    * 显示栏目菜单列表
    */
public function public_categorys() {
    $show_header = '';
    $cfg = getcache('common','commons');
    $ajax_show = intval($cfg['category_ajax']);
    $from = isset($_GET['from']) && in_array($_GET['from'],array('block')) ? $_GET['from'] : 'content';
    $tree = pc_base::load_sys_class('tree');
    if($from=='content' && $_SESSION['roleid'] != 1) {    
        $this->priv_db = pc_base::load_model('category_priv_model');
        $priv_result = $this->priv_db->select(array('action'=>'init','roleid'=>$_SESSION['roleid'],'siteid'=>$this->siteid,'is_admin'=>1));
        $priv_catids = array();
        foreach($priv_result as $_v) {
            $priv_catids[] = $_v['catid'];
        }
        if(empty($priv_catids)) return '';
    }
    $categorys = array();
    if(!empty($this->categorys)) {
        foreach($this->categorys as $r) {
            if($r['siteid']!=$this->siteid ||  ($r['type']==2 && $r['child']==0)) continue;
            if($from=='content' && $_SESSION['roleid'] != 1 && !in_array($r['catid'],$priv_catids)) {
                $arrchildid = explode(',',$r['arrchildid']);
                $array_intersect = array_intersect($priv_catids,$arrchildid);
                if(empty($array_intersect)) continue;
            }
            if($r['type']==1 || $from=='block') {
                if($r['type']==0) {
                    $r['vs_show'] = "<a href='?m=block&c=block_admin&a=public_visualization&menuid=".$_GET['menuid']."&catid=".$r['catid']."&type=show' target='right'>[".L('content_page')."]</a>";
                } else {
                    $r['vs_show'] ='';
                }
                $r['icon_type'] = 'file';
                $r['add_icon'] = '';
                $r['type'] = 'add';
            } else {
                $r['icon_type'] = $r['vs_show'] = '';
                $r['type'] = 'init';
                $r['add_icon'] = "<a target='right' href='?m=content&c=content&menuid=".$_GET['menuid']."&catid=".$r['catid']."' onclick=javascript:openwinx('?m=content&c=content&a=add&menuid=".$_GET['menuid']."&catid=".$r['catid']."&hash_page=".$_SESSION['hash_page']."','')><img src='".IMG_PATH."add_content.gif' alt='".L('add')."'></a> ";
            }
            $categorys[$r['catid']] = $r;
        }
    }
    if(!empty($categorys)) {
        $tree->init($categorys);
            switch($from) {
                case 'block':
                    $strs = "<span class='\$icon_type'>\$add_icon<a href='?m=block&c=block_admin&a=public_visualization&menuid=".$_GET['menuid']."&catid=\$catid&type=list' target='right'>\$catname</a> \$vs_show</span>";
                    $strs2 = "<img src='".IMG_PATH."folder.gif'> <a href='?m=block&c=block_admin&a=public_visualization&menuid=".$_GET['menuid']."&catid=\$catid&type=category' target='right'>\$catname</a>";
                break;

                default:
                    $strs = "<span class='\$icon_type'>\$add_icon<a href='?m=content&c=content&a=\$type&menuid=".$_GET['menuid']."&catid=\$catid' target='right' onclick='open_list(this)'>\$catname</a></span>";
                    //修改前
                    //$strs2 = "<span class='folder'>\$catname</span>";
                    //修改后
                    $strs2 = "<span class='\$icon_type'>\$add_icon<a href='?m=content&c=content&a=\$type&menuid=".$_GET['menuid']."&catid=\$catid' target='right' onclick='open_list(this)'>\$catname</a></span>";
                    break;
            }
        $categorys = $tree->get_treeview(0,'category_tree',$strs,$strs2,$ajax_show);
    } else {
        $categorys = L('please_add_category');
    }
    include $this->admin_tpl('category_tree');
    exit;
}

其实就是把$strs2改成和$strs相同的代码

1
2
3
4
5
$strs = "<span class='\$icon_type'>\$add_icon<a href='?m=content&c=content&a=\$type&menuid=".$_GET['menuid']."&catid=\$catid' target='right' onclick='open_list(this)'>\$catname</a></span>";
//修改前
//$strs2 = "<span class='folder'>\$catname</span>";
//修改后
$strs2 = "<span class='\$icon_type'>\$add_icon<a href='?m=content&c=content&a=\$type&menuid=".$_GET['menuid']."&catid=\$catid' target='right' onclick='open_list(this)'>\$catname</a></span>";

二 截图如下:(截图也用的原来的,反正只是一个示例)

三 在category页面中搜索具有子栏目的当前栏目的文章
情节描述:在phpcms V9版本中 如果一个栏目有子栏目,那么系统会使用在后台设置中 内容->栏目管理->添加\修改->模板设置->栏目首页模板(简称栏目页面) 中规定的页面
在phpcms V9版本中 如果一个栏目下就是文章,那么系统会使用在后台设置中 内容->栏目管理->添加\修改->模板设置->栏目列表页模板(简称列表页面) 中规定的页面
在当前情景下当前栏目有子栏目也有文章那么默认还是会找 内容->栏目管理->添加\修改->模板设置->栏目首页模板 (当然这个可以通过程序修改,但是不建议这么做)
在当前栏目页面中使用pc标签查找栏目下文章{pc:content action="lists” catid="$catid” num="43” order="id DESC” moreinfo="1” page="$_GET[page]"}
注意使用的是lists方法,
现在查看这个调用方法的代码 代码文件为 phpcms/modules/content/classes/content_tag.class.php

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
/**
    * 列表页标签
    * @param $data
    */
public function lists($data) {
    $catid = intval($data['catid']);if(!$this->set_modelid($catid)) return false;
    if(isset($data['where'])) {
        $sql = $data['where'];
    } else {
        $thumb = intval($data['thumb']) ? " AND thumb != ''" : '';
        //如果有子栏目
        //注意这个判断,如果要查询的栏目id下有子栏目,那么$sql 拼接sql语句的条件就不是catid等于当前要查询的id了
        
        if($this->category[$catid]['child']) {
            $catids_str = $this->category[$catid]['arrchildid'];
            $pos = strpos($catids_str,',')+1;
            $catids_str = substr($catids_str, $pos);
            $sql = "status=99 AND catid IN ($catids_str)".$thumb;
        } else {
            $sql = "status=99 AND catid='$catid'".$thumb;
        }
    }
    $order = $data['order'];

    $return = $this->db->select($sql, '*', $data['limit'], $order, '', 'id');
    //调用副表的数据
    if (isset($data['moreinfo']) && intval($data['moreinfo']) == 1) {
        $ids = array();
        foreach ($return as $v) {
            if (isset($v['id']) && !empty($v['id'])) {
                $ids[] = $v['id'];
            } else {
                continue;
            }
        }
        if (!empty($ids)) {
            $this->db->table_name = $this->db->table_name.'_data';
            $ids = implode('\',\'', $ids);
            $r = $this->db->select("`id` IN ('$ids')", '*', '', '', '', 'id');
            if (!empty($r)) {
                foreach ($r as $k=>$v) {
                    if (isset($return[$k])) $return[$k] = array_merge($v, $return[$k]);
                }
            }
        }
    }
    return $return;
}

注意上述代码中注释部分

所以这里我做如下修改

调用pc标签 {pc:content action="lists” catid="14” num="43” order="id DESC” moreinfo="1” page="$_GET[page]” curlist="1”} 这里我自己添加了一个参数curlist="1”

在上面的代码中把if($this->category[$catid][‘child’]) 改成if($this->category[$catid][‘child’] && empty($data[‘curlist’]))这样就可以查询有子栏目的当前栏目的文章列表了

四 在开发中发现使用上述方法后确实可以在栏目页调用到文章列表了,但是这个列表是不能分页的这需要也在phpcms/modules/content/classes/content_tag.class.php文件中修改public function count方法

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
/**
    * 分页统计
    * @param $data
    */
public function count($data) {
    if($data['action'] == 'lists') {
        $catid = intval($data['catid']);
        if(!$this->set_modelid($catid)) return false;
        if(isset($data['where'])) {
            $sql = $data['where'];
        } else {
            //同样是吧 if($this->category[$catid]['child']) 改成if($this->category[$catid]['child'] && empty($data['curlist']))
            if($this->category[$catid]['child'] && empty($data['curlist'])) {
                $catids_str = $this->category[$catid]['arrchildid'];
                $pos = strpos($catids_str,',')+1;
                $catids_str = substr($catids_str, $pos);
                $sql = "status=99 AND catid IN ($catids_str)";
            } else {
                $sql = "status=99 AND catid='$catid'";
            }
        }
        return $this->db->count($sql);
    }
}

具体原理藏得计较深,简单说明一下
因为pc的左右页面通过框架要解析模板所以在lib/classes/template_cache.class.php文件中public static function pc_tag()方法代码如下

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
/**
    * 解析PC标签
    * @param string $op 操作方式
    * @param string $data 参数
    * @param string $html 匹配到的所有的HTML代码
    */
public static function pc_tag($op, $data, $html) {
    preg_match_all("/([a-z]+)\=[\"]?([^\"]+)[\"]?/i", stripslashes($data), $matches, PREG_SET_ORDER);
    $arr = array('action','num','cache','page', 'pagesize', 'urlrule', 'return', 'start');
    $tools = array('json', 'xml', 'block', 'get');
    $datas = array();
    $tag_id = md5(stripslashes($html));
    //可视化条件
    $str_datas = 'op='.$op.'&tag_md5='.$tag_id;
    foreach ($matches as $v) {
        $str_datas .= $str_datas ? "&$v[1]=".($op == 'block' && strpos($v[2], '$') === 0 ? $v[2] : urlencode($v[2])) : "$v[1]=".(strpos($v[2], '$') === 0 ? $v[2] : urlencode($v[2]));
        if(in_array($v[1], $arr)) {
            $$v[1] = $v[2];
            continue;
        }
        $datas[$v[1]] = $v[2];
    }
    $str = '';
    $num = isset($num) && intval($num) ? intval($num) : 20;
    $cache = isset($cache) && intval($cache) ? intval($cache) : 0;
    $return = isset($return) && trim($return) ? trim($return) : 'data';
    if (!isset($urlrule)) $urlrule = '';
    if (!empty($cache) && !isset($page)) {
        $str .= '$tag_cache_name = md5(implode(\'&\','.self::arr_to_html($datas).').\''.$tag_id.'\');if(!$'.$return.' = tpl_cache($tag_cache_name,'.$cache.')){';
    }
    if (in_array($op,$tools)) {
        switch ($op) {
            case 'json':
                    if (isset($datas['url']) && !empty($datas['url'])) {
                        $str .= '$json = @file_get_contents(\''.$datas['url'].'\');';
                        $str .= '$'.$return.' = json_decode($json, true);';
                    }
                break;
                
            case 'xml':
                    $str .= '$xml = pc_base::load_sys_class(\'xml\');';
                    $str .= '$xml_data = @file_get_contents(\''.$datas['url'].'\');';
                    $str .= '$'.$return.' = $xml->xml_unserialize($xml_data);';
                break;
                
            case 'get':
                    $str .= 'pc_base::load_sys_class("get_model", "model", 0);';
                    if ($datas['dbsource']) {
                        $dbsource = getcache('dbsource', 'commons');
                        if (isset($dbsource[$datas['dbsource']])) {
                            $str .= '$get_db = new get_model('.var_export($dbsource,true).', \''.$datas['dbsource'].'\');';
                        } else {
                            return false;
                        }
                    } else {
                        $str .= '$get_db = new get_model();';
                    }
                    $num = isset($num) && intval($num) > 0 ? intval($num) : 20;
                    if (isset($start) && intval($start)) {
                        $limit = intval($start).','.$num;
                    } else {
                        $limit = $num;
                    }
                    if (isset($page)) {
                        $str .= '$pagesize = '.$num.';';
                        $str .= '$page = intval('.$page.') ? intval('.$page.') : 1;if($page<=0){$page=1;}';
                        $str .= '$offset = ($page - 1) * $pagesize;';
                        $limit = '$offset,$pagesize';
                        $sql = 'SELECT COUNT(*) as count FROM ('.$datas['sql'].') T';
                        $str .= '$r = $get_db->sql_query("'.$sql.'");$s = $get_db->fetch_next();$pages=pages($s[\'count\'], $page, $pagesize, $urlrule);';
                    }
                    
                    
                    $str .= '$r = $get_db->sql_query("'.$datas['sql'].' LIMIT '.$limit.'");while(($s = $get_db->fetch_next()) != false) {$a[] = $s;}$'.$return.' = $a;unset($a);';
                break;
                
            case 'block':
                $str .= '$block_tag = pc_base::load_app_class(\'block_tag\', \'block\');';
                $str .= 'echo $block_tag->pc_tag('.self::arr_to_html($datas).');';
                break;
        }
    } else {
        if (!isset($action) || empty($action)) return false;
        if (module_exists($op) && file_exists(PC_PATH.DIRECTORY_SEPARATOR.'modules'.DIRECTORY_SEPARATOR.$op.DIRECTORY_SEPARATOR.'classes'.DIRECTORY_SEPARATOR.$op.'_tag.class.php')) {
            $str .= '$'.$op.'_tag = pc_base::load_app_class("'.$op.'_tag", "'.$op.'");if (method_exists($'.$op.'_tag, \''.$action.'\')) {';    
            if (isset($start) && intval($start)) {
                $datas['limit'] = intval($start).','.$num;
            } else {
                $datas['limit'] = $num;
            }
            if (isset($page)) {
                $str .= '$pagesize = '.$num.';';
                $str .= '$page = intval('.$page.') ? intval('.$page.') : 1;if($page<=0){$page=1;}';
                $str .= '$offset = ($page - 1) * $pagesize;';
                $datas['limit'] = '$offset.",".$pagesize';
                $datas['action'] = $action;
                $str .= '$'.$op.'_total = $'.$op.'_tag->count('.self::arr_to_html($datas).');';
                $str .= '$pages = pages($'.$op.'_total, $page, $pagesize, $urlrule);';
            }
            $str .= '$'.$return.' = $'.$op.'_tag->'.$action.'('.self::arr_to_html($datas).');';
            $str .= '}';
            //echo $str;103             } 
    }
    if (!empty($cache) && !isset($page)) {
        $str .= 'if(!empty($'.$return.')){setcache($tag_cache_name, $'.$return.', \'tpl_data\');}';
        $str .= '}';
    }
    return "<"."?php if(defined('IN_ADMIN')  && !defined('HTML')) {echo \"<div class=\\\"admin_piao\\\" pc_action=\\\"".$op."\\\" data=\\\"".$str_datas."\\\"><a href=\\\"javascript:void(0)\\\" class=\\\"admin_piao_edit\\\">".($op=='block' ? L('block_add') : L('edit'))."</a>\";}".$str."?".">";
}

经过分析,因为我们的对象为$op == “content”
在if (in_array($op,$tools)){}else{}中会进入到esle中,这里最关键的就是一个名为$str的变量,在注释的位置打印这个变量得到如下代码

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
$content_tag = pc_base::load_app_class("content_tag", "content");

if (method_exists($content_tag, 'category')) {
    $data = $content_tag->category(array('catid'=>$catid,'siteid'=>$siteid,'order'=>'listorder ASC','limit'=>'25',));
}

$content_tag = pc_base::load_app_class("content_tag", "content");

if (method_exists($content_tag, 'lists')) {
    $pagesize = 1;
    $page = intval($_GET[page]) ? intval($_GET[page]) : 1;
    if($page<=0){$page=1;}
    $offset = ($page - 1) * $pagesize;
    $content_total = $content_tag->count(array('catid'=>$catid,'order'=>'id DESC','moreinfo'=>'1','curlist'=>'1','limit'=>$offset.",".$pagesize,'action'=>'lists',));
    $pages = pages($content_total, $page, $pagesize, $urlrule);
    $data = $content_tag->lists(array('catid'=>$catid,'order'=>'id DESC','moreinfo'=>'1','curlist'=>'1','limit'=>$offset.",".$pagesize,'action'=>'lists',));
}

在这里我们关注的lists方法所以重点看第7行以后的代码
$content_tag = pc_base::load_app_class(“content_tag”, “content”);实例化了content模块下的content_tag类
method_exists($content_tag, ‘lists’) 为真 所以到13行去请求了content_tag->count()方法,传值为’catid'=>$catid,再回到第四节刚开始的public function count方法里,就知道要修改的原因了,
也用了同样的参数’curlist'=>'1'来限定我一定是要列表,和第三节的理由相同,
到这里栏目中调用文章列表也可以分页了

2015-05-25 更新
五 关于后台功能 后台 —– 内容 —– 批量更新url —– 不限模型不限栏目的情况下,不能更新有子栏目的父栏目下文章的url的问题
其实关于这个问题,可以通过选择更新某一个文章模型来解决这个问题,但是这里还是贴出来怎么来修改这个问题
批量更新url功能的连接是 ?m=content&c=create_html&a=update_urls 根据pc的统一惯例,表单显示和处理表单都肯定用一个方法,
这里只列出怎么修改代码,具体的代码执行跟踪不多赘述,代码如下

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
public function update_urls() {
    //判断是表单提交
    if(isset($_POST['dosubmit'])) {
        extract($_POST,EXTR_SKIP);
        $this->url = pc_base::load_app_class('url');

        $modelid = intval($_POST['modelid']);
        // 如果是按照模型来更新,重点不在这里
        if($modelid) {

            //更新模型url的一些代码
            //......

        } else {
                        
            //当没有选择模型时,需要按照栏目来更新
            //这里才是重点
            if(!isset($set_catid)) {
                //如果选择了具体的栏目
                if($catids[0] != 0) {
                    $update_url_catids = $catids;
                } 
                //如果没选择具体的栏目
                else {

                    foreach($this->categorys as $catid=>$cat) {
                        //这里是要过滤带有子栏目的,把下面这个屏蔽掉,就可以更新咱们的目标的父栏目了,但是看最后一个条件$cat['type']!=0,例如当栏目类型==1时,是单页栏目,这里要单独打开判断
                           $cat['child'] 判断是否有子栏目,$cat['siteid'] != $this->siteid 不适当前站点的栏目(适用于站群),$cat['type']!=0 不是普通栏目
                        //if($cat['child'] || $cat['siteid'] != $this->siteid || $cat['type']!=0) continue;
                        if($cat['type']!=0) continue;
                        $update_url_catids[] = $catid;
                    }
                }
                                    
                setcache('update_url_catid'.'-'.$this->siteid.'-'.$_SESSION['userid'],$update_url_catids,'content');
                $message = L('start_update_urls');
                $forward = "?m=content&c=create_html&a=update_urls&set_catid=1&pagesize=$pagesize&dosubmit=1";
                //显示  正在更新某个栏目 在200毫秒后跳转到$forward指示的地址
                showmessage($message,$forward,200);
            }
            //一些执行的操作......
        }

    } 
    //不是表单提交
    else {
        $show_header = $show_dialog  = '';
            $admin_username = param::get_cookie('admin_username');
            $modelid = isset($_GET['modelid']) ? intval($_GET['modelid']) : 0;
            
            $tree = pc_base::load_sys_class('tree');
            $tree->icon = array('&nbsp;&nbsp;&nbsp;│ ','&nbsp;&nbsp;&nbsp;├─ ','&nbsp;&nbsp;&nbsp;└─ ');
            $tree->nbsp = '&nbsp;&nbsp;&nbsp;';
            $categorys = array();
            if(!empty($this->categorys)) {
                foreach($this->categorys as $catid=>$r) {
                    if($this->siteid != $r['siteid'] || ($r['type']!=0 && $r['child']==0)) continue;
                    if($modelid && $modelid != $r['modelid']) continue;
                    //这里屏蔽掉就可以在后天单独选择某一个父栏目来更新,否则是disabled禁用
                    //$r['disabled'] = $r['child'] ? 'disabled禁用' : '';
                    $categorys[$catid] = $r;
                }
            }
            $str  = "<option value='\$catid' \$selected \$disabled>\$spacer \$catname</option>";

            $tree->init($categorys);
            $string .= $tree->get_tree(0, $str);
            include $this->admin_tpl('update_urls');
    }
}

看上述代码26行和57行的注释,这样问题就解决了,可以更新所有的栏目了

分享

Koala An
作者
Koala An
一个大自然的搬运工