对于题目的解释:
假设现在有一个一级栏目 为:栏目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 public function public_categorys() { 5 $show_header = ‘‘; 6 $cfg = getcache(‘common‘,‘commons‘); 7 $ajax_show = intval($cfg[‘category_ajax‘]); 8 $from = isset($_GET[‘from‘]) && in_array($_GET[‘from‘],array(‘block‘)) ? $_GET[‘from‘] : ‘content‘; 9 $tree = pc_base::load_sys_class(‘tree‘); 10 if($from==‘content‘ && $_SESSION[‘roleid‘] != 1) { 11 $this->priv_db = pc_base::load_model(‘category_priv_model‘); 12 $priv_result = $this->priv_db->select(array(‘action‘=>‘init‘,‘roleid‘=>$_SESSION[‘roleid‘],‘siteid‘=>$this->siteid,‘is_admin‘=>1)); 13 $priv_catids = array(); 14 foreach($priv_result as $_v) { 15 $priv_catids[] = $_v[‘catid‘]; 16 } 17 if(empty($priv_catids)) return ‘‘; 18 } 19 $categorys = array(); 20 if(!empty($this->categorys)) { 21 foreach($this->categorys as $r) { 22 if($r[‘siteid‘]!=$this->siteid || ($r[‘type‘]==2 && $r[‘child‘]==0)) continue; 23 if($from==‘content‘ && $_SESSION[‘roleid‘] != 1 && !in_array($r[‘catid‘],$priv_catids)) { 24 $arrchildid = explode(‘,‘,$r[‘arrchildid‘]); 25 $array_intersect = array_intersect($priv_catids,$arrchildid); 26 if(empty($array_intersect)) continue; 27 } 28 if($r[‘type‘]==1 || $from==‘block‘) { 29 if($r[‘type‘]==0) { 30 $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>"; 31 } else { 32 $r[‘vs_show‘] =‘‘; 33 } 34 $r[‘icon_type‘] = ‘file‘; 35 $r[‘add_icon‘] = ‘‘; 36 $r[‘type‘] = ‘add‘; 37 } else { 38 $r[‘icon_type‘] = $r[‘vs_show‘] = ‘‘; 39 $r[‘type‘] = ‘init‘; 40 $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> "; 41 } 42 $categorys[$r[‘catid‘]] = $r; 43 } 44 } 45 if(!empty($categorys)) { 46 $tree->init($categorys); 47 switch($from) { 48 case ‘block‘: 49 $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>"; 50 $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>"; 51 break; 52 53 default: 54 $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>"; 55 //修改前 56 //$strs2 = "<span class=‘folder‘>\$catname</span>"; 57 //修改后 58 $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>"; 59 break; 60 } 61 $categorys = $tree->get_treeview(0,‘category_tree‘,$strs,$strs2,$ajax_show); 62 } else { 63 $categorys = L(‘please_add_category‘); 64 } 65 include $this->admin_tpl(‘category_tree‘); 66 exit; 67 }
其实就是把$strs2改成和$strs相同的代码
$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
/** * 列表页标签 * @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方法
/** * 分页统计 * @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 * 解析PC标签 3 * @param string $op 操作方式 4 * @param string $data 参数 5 * @param string $html 匹配到的所有的HTML代码 6 */ 7 public static function pc_tag($op, $data, $html) { 8 preg_match_all("/([a-z]+)\=[\"]?([^\"]+)[\"]?/i", stripslashes($data), $matches, PREG_SET_ORDER); 9 $arr = array(‘action‘,‘num‘,‘cache‘,‘page‘, ‘pagesize‘, ‘urlrule‘, ‘return‘, ‘start‘); 10 $tools = array(‘json‘, ‘xml‘, ‘block‘, ‘get‘); 11 $datas = array(); 12 $tag_id = md5(stripslashes($html)); 13 //可视化条件 14 $str_datas = ‘op=‘.$op.‘&tag_md5=‘.$tag_id; 15 foreach ($matches as $v) { 16 $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])); 17 if(in_array($v[1], $arr)) { 18 $$v[1] = $v[2]; 19 continue; 20 } 21 $datas[$v[1]] = $v[2]; 22 } 23 $str = ‘‘; 24 $num = isset($num) && intval($num) ? intval($num) : 20; 25 $cache = isset($cache) && intval($cache) ? intval($cache) : 0; 26 $return = isset($return) && trim($return) ? trim($return) : ‘data‘; 27 if (!isset($urlrule)) $urlrule = ‘‘; 28 if (!empty($cache) && !isset($page)) { 29 $str .= ‘$tag_cache_name = md5(implode(\‘&\‘,‘.self::arr_to_html($datas).‘).\‘‘.$tag_id.‘\‘);if(!$‘.$return.‘ = tpl_cache($tag_cache_name,‘.$cache.‘)){‘; 30 } 31 if (in_array($op,$tools)) { 32 switch ($op) { 33 case ‘json‘: 34 if (isset($datas[‘url‘]) && !empty($datas[‘url‘])) { 35 $str .= ‘$json = @file_get_contents(\‘‘.$datas[‘url‘].‘\‘);‘; 36 $str .= ‘$‘.$return.‘ = json_decode($json, true);‘; 37 } 38 break; 39 40 case ‘xml‘: 41 $str .= ‘$xml = pc_base::load_sys_class(\‘xml\‘);‘; 42 $str .= ‘$xml_data = @file_get_contents(\‘‘.$datas[‘url‘].‘\‘);‘; 43 $str .= ‘$‘.$return.‘ = $xml->xml_unserialize($xml_data);‘; 44 break; 45 46 case ‘get‘: 47 $str .= ‘pc_base::load_sys_class("get_model", "model", 0);‘; 48 if ($datas[‘dbsource‘]) { 49 $dbsource = getcache(‘dbsource‘, ‘commons‘); 50 if (isset($dbsource[$datas[‘dbsource‘]])) { 51 $str .= ‘$get_db = new get_model(‘.var_export($dbsource,true).‘, \‘‘.$datas[‘dbsource‘].‘\‘);‘; 52 } else { 53 return false; 54 } 55 } else { 56 $str .= ‘$get_db = new get_model();‘; 57 } 58 $num = isset($num) && intval($num) > 0 ? intval($num) : 20; 59 if (isset($start) && intval($start)) { 60 $limit = intval($start).‘,‘.$num; 61 } else { 62 $limit = $num; 63 } 64 if (isset($page)) { 65 $str .= ‘$pagesize = ‘.$num.‘;‘; 66 $str .= ‘$page = intval(‘.$page.‘) ? intval(‘.$page.‘) : 1;if($page<=0){$page=1;}‘; 67 $str .= ‘$offset = ($page - 1) * $pagesize;‘; 68 $limit = ‘$offset,$pagesize‘; 69 $sql = ‘SELECT COUNT(*) as count FROM (‘.$datas[‘sql‘].‘) T‘; 70 $str .= ‘$r = $get_db->sql_query("‘.$sql.‘");$s = $get_db->fetch_next();$pages=pages($s[\‘count\‘], $page, $pagesize, $urlrule);‘; 71 } 72 73 74 $str .= ‘$r = $get_db->sql_query("‘.$datas[‘sql‘].‘ LIMIT ‘.$limit.‘");while(($s = $get_db->fetch_next()) != false) {$a[] = $s;}$‘.$return.‘ = $a;unset($a);‘; 75 break; 76 77 case ‘block‘: 78 $str .= ‘$block_tag = pc_base::load_app_class(\‘block_tag\‘, \‘block\‘);‘; 79 $str .= ‘echo $block_tag->pc_tag(‘.self::arr_to_html($datas).‘);‘; 80 break; 81 } 82 } else { 83 if (!isset($action) || empty($action)) return false; 84 if (module_exists($op) && file_exists(PC_PATH.DIRECTORY_SEPARATOR.‘modules‘.DIRECTORY_SEPARATOR.$op.DIRECTORY_SEPARATOR.‘classes‘.DIRECTORY_SEPARATOR.$op.‘_tag.class.php‘)) { 85 $str .= ‘$‘.$op.‘_tag = pc_base::load_app_class("‘.$op.‘_tag", "‘.$op.‘");if (method_exists($‘.$op.‘_tag, \‘‘.$action.‘\‘)) {‘; 86 if (isset($start) && intval($start)) { 87 $datas[‘limit‘] = intval($start).‘,‘.$num; 88 } else { 89 $datas[‘limit‘] = $num; 90 } 91 if (isset($page)) { 92 $str .= ‘$pagesize = ‘.$num.‘;‘; 93 $str .= ‘$page = intval(‘.$page.‘) ? intval(‘.$page.‘) : 1;if($page<=0){$page=1;}‘; 94 $str .= ‘$offset = ($page - 1) * $pagesize;‘; 95 $datas[‘limit‘] = ‘$offset.",".$pagesize‘; 96 $datas[‘action‘] = $action; 97 $str .= ‘$‘.$op.‘_total = $‘.$op.‘_tag->count(‘.self::arr_to_html($datas).‘);‘; 98 $str .= ‘$pages = pages($‘.$op.‘_total, $page, $pagesize, $urlrule);‘; 99 } 100 $str .= ‘$‘.$return.‘ = $‘.$op.‘_tag->‘.$action.‘(‘.self::arr_to_html($datas).‘);‘; 101 $str .= ‘}‘; 102 //echo $str;103 } 104 } 105 if (!empty($cache) && !isset($page)) { 106 $str .= ‘if(!empty($‘.$return.‘)){setcache($tag_cache_name, $‘.$return.‘, \‘tpl_data\‘);}‘; 107 $str .= ‘}‘; 108 } 109 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."?".">"; 110 }
经过分析,因为我们的对象为$op == "content"在if (in_array($op,$tools)){}else{}中会进入到esle中,这里最关键的就是一个名为$str的变量,在注释的位置打印这个变量得到如下代码
1 $content_tag = pc_base::load_app_class("content_tag", "content"); 2 3 if (method_exists($content_tag, ‘category‘)) { 4 $data = $content_tag->category(array(‘catid‘=>$catid,‘siteid‘=>$siteid,‘order‘=>‘listorder ASC‘,‘limit‘=>‘25‘,)); 5 } 6 7 $content_tag = pc_base::load_app_class("content_tag", "content"); 8 9 if (method_exists($content_tag, ‘lists‘)) { 10 $pagesize = 1; 11 $page = intval($_GET[page]) ? intval($_GET[page]) : 1; 12 if($page<=0){$page=1;} 13 $offset = ($page - 1) * $pagesize; 14 $content_total = $content_tag->count(array(‘catid‘=>$catid,‘order‘=>‘id DESC‘,‘moreinfo‘=>‘1‘,‘curlist‘=>‘1‘,‘limit‘=>$offset.",".$pagesize,‘action‘=>‘lists‘,)); 15 $pages = pages($content_total, $page, $pagesize, $urlrule); 16 $data = $content_tag->lists(array(‘catid‘=>$catid,‘order‘=>‘id DESC‘,‘moreinfo‘=>‘1‘,‘curlist‘=>‘1‘,‘limit‘=>$offset.",".$pagesize,‘action‘=>‘lists‘,)); 17 }
在这里我们关注的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‘来限定我一定是要列表,和第三节的理由相同,到这里栏目中调用文章列表也可以分页了