原始數據
$array = array( array('id' => 1, 'pid' => 0, 'n' => '河北省'), array('id' => 2, 'pid' => 0, 'n' => '北京市'), array('id' => 3, 'pid' => 1, 'n' => '邯鄲市'), array('id' => 4, 'pid' => 2, 'n' => '朝陽區'), array('id' => 5, 'pid' => 2, 'n' => '通州區'), array('id' => 6, 'pid' => 4, 'n' => '望京'), array('id' => 7, 'pid' => 4, 'n' => '酒仙橋'), array('id' => 8, 'pid' => 3, 'n' => '永年區'), array('id' => 9, 'pid' => 1, 'n' => '武安市'), array('id' => 10, 'pid' => 8, 'n' => '永年區鎮'), array('id' => 11, 'pid' => 0, 'n' => '上海市') );
生成無限極分類
/** 所有的分類 * @parem $array 數組 * @parem $pid ,最高級別,默認為0,輸出從pid 級別的數據 * @parem $level 層級,默認0 * */ function getTree($array, $pid =0, $level = 0){ $f_name=__FUNCTION__; // 定義當前函數名 //聲明靜態數組,避免遞歸調用時,多次聲明導致數組覆蓋 static $list = []; foreach ($array as $key => $value){ //第一次遍歷,找到父節點為根節點的節點 也就是pid=0的節點 if ($value['pid'] == $pid){ //父節點為根節點的節點,級別為0,也就是第一級 $flg = str_repeat('|--',$level); // 更新 名稱值 $value['n'] = $flg.$value['n']; // 輸出 名稱 echo $value['n']."<br/>"; //把數組放到list中 $list[] = $value; //把這個節點從數組中移除,減少后續遞歸消耗 unset($array[$key]); //開始遞歸,查找父ID為該節點ID的節點,級別則為原級別+1 $f_name($array, $value['id'], $level+1); } } return $list; } // 調用 $list=getTree($array);
調用結果:
河北省 |--邯鄲市 |--|--永年區 |--|--|--永年區鎮 |--武安市 北京市 |--朝陽區 |--|--望京 |--|--酒仙橋 |--通州區
嵌套標簽,前端可以(通過選取子節點)全選、取消全選
function getTree($array, $pid =0, $level = 0){ $f_name=__FUNCTION__; // 定義當前函數名 // 空數組 不在執行 if(empty($array)) return; //聲明靜態數組,避免遞歸調用時,多次聲明導致數組覆蓋 static $html; $html.="<ul>"; foreach ($array as $key => $value){ //第一次遍歷,找到父節點為根節點的節點 也就是pid=0的節點 if ($value['pid'] == $pid){ //父節點為根節點的節點,級別為0,也就是第一級 $flg = str_repeat('|--',$level); // 更新 名稱值 $value['n'] = $flg.$value['n']; $html.=$temp="<li><input type=\"checkbox\" name=\"limit_id[]\" value='".$value['id']."' >".$value['n']; //把這個節點從數組中移除,減少后續遞歸消耗 unset($array[$key]); //開始遞歸,查找父ID為該節點ID的節點,級別則為原級別+1 $vv=$f_name($array, $value['id'], $level+1); // 如果頂級分類下沒有一個下級,刪除此分類,此步驟可以省略 if(empty($vv) && ($pid<1)) { $html=str_replace($temp,'',$html); } $html.="</li>\r\n"; } } $html.="</ul>\r\n"; // 刪除多余的 ul 標簽 $html=str_replace("<ul></ul>",'',$html); return $html; }
html 輸出結果
<ul>
<li><input type="checkbox" name="limit_id[]" value='1'>河北省
<ul>
<li><input type="checkbox" name="limit_id[]" value='3'>|--邯鄲市
<ul>
<li><input type="checkbox" name="limit_id[]" value='8'>|--|--永年區
<ul>
<li><input type="checkbox" name="limit_id[]" value='10'>|--|--|--永年區鎮
</li>
</ul>
</li>
</ul>
</li>
<li><input type="checkbox" name="limit_id[]" value='9'>|--武安市
</li>
</ul>
</li>
<li><input type="checkbox" name="limit_id[]" value='2'>北京市
<ul>
<li><input type="checkbox" name="limit_id[]" value='4'>|--朝陽區
<ul>
<li><input type="checkbox" name="limit_id[]" value='6'>|--|--望京
</li>
<li><input type="checkbox" name="limit_id[]" value='7'>|--|--酒仙橋
</li>
</ul>
</li>
<li><input type="checkbox" name="limit_id[]" value='5'>|--通州區
</li>
</ul>
</li>
</li>
</ul>
jquery 操作全選
//父級選中 自動選中子級,同時選中自己的父級 $('input[type="checkbox"]').change(function(e) { var checked = $(this).prop("checked"), container = $(this).parent(), siblings = container.siblings(); container.find('input[type="checkbox"]').prop({ indeterminate: false, checked: checked }); function checkSiblings(el) { var parent = el.parent().parent(), all = true; el.siblings().each(function() { return all = ($(this).children('input[type="checkbox"]').prop("checked") === checked); }); if (all && checked) { parent.children('input[type="checkbox"]').prop({ indeterminate: false, checked: checked }); checkSiblings(parent); } else if (all && !checked) { parent.children('input[type="checkbox"]').prop("checked", checked); parent.children('input[type="checkbox"]').prop("indeterminate", (parent.find('input[type="checkbox"]:checked').length > 0)); checkSiblings(parent); } else { el.parents("li").children('input[type="checkbox"]').prop({ indeterminate: true, checked: false }); } } checkSiblings(container); }); // 父級選中 自動選中子級 /*$("input[type=checkbox]").each(function (i,ele){ let _this=$(this); _this.click(function(){ if(_this.prop('checked')==true) { _this.parent().find('ul input').prop('checked',true); }else { _this.parent().find('ul input').prop('checked',false); } }); });*/
數組嵌套
引用嵌套,php變量默認的傳值方式是按指傳遞,也就是說 假如說 遍歷順序是 河北省 邯鄲市 當遍歷到河北省時需要把河北省放到tree中,遍歷到邯鄲市時,需要把邯鄲市放到河北省的子節點數組中,所以這里用到了引用傳遞,當你對河北省做更改時,tree數組中的河北省也一並做了更改
function getTree($list, $pid = 0) { $tree = []; if (!empty($list)) { $newList = []; foreach ($list as $k => $v) { $newList[$v['id']] = $v; } foreach ($newList as $value ) { if ($pid == $value['pid']) { $tree[] = &$newList[$value['id']]; } elseif (isset($newList[$value['pid']])) { $newList[$value['pid']]['items'][] = &$newList[$value['id']]; } } // 如果頂級分類下沒有一個下級,刪除此分類,此步驟可以省略 foreach ($tree as $k=>$v) { if(!isset($v['items']) && ($pid<1)) unset($tree[$k]); } } return $tree; } // 調用 $list=getTree($array); var_dump($list);
顯示結果
array(2) { [0]=> array(4) { ["id"]=> int(1) ["pid"]=> int(0) ["n"]=> string(9) "河北省" ["items"]=> array(2) { [0]=> array(4) { ["id"]=> int(3) ["pid"]=> int(1) ["n"]=> string(9) "邯鄲市" ["items"]=> array(1) { [0]=> array(4) { ["id"]=> int(8) ["pid"]=> int(3) ["n"]=> string(9) "永年區" ["items"]=> array(1) { [0]=> array(3) { ["id"]=> int(10) ["pid"]=> int(8) ["n"]=> string(12) "永年區鎮" } } } } } [1]=> array(3) { ["id"]=> int(9) ["pid"]=> int(1) ["n"]=> string(9) "武安市" } } } [1]=> array(4) { ["id"]=> int(2) ["pid"]=> int(0) ["n"]=> string(9) "北京市" ["items"]=> array(2) { [0]=> array(4) { ["id"]=> int(4) ["pid"]=> int(2) ["n"]=> string(9) "朝陽區" ["items"]=> array(2) { [0]=> array(3) { ["id"]=> int(6) ["pid"]=> int(4) ["n"]=> string(6) "望京" } [1]=> array(3) { ["id"]=> int(7) ["pid"]=> int(4) ["n"]=> string(9) "酒仙橋" } } } [1]=> array(3) { ["id"]=> int(5) ["pid"]=> int(2) ["n"]=> string(9) "通州區" } } } }
根據子類id查找出所有父級分類信息
/**根據指定id 的查詢,所有的父節點 * @parem $id_pid 要查詢的id 或者 要查詢id的pid;如果傳入的是id 包括當前id 值,如果傳入id_pid不包括當前id的值 * @parem $array 查分類的數據,在項目使用中此參數可以不傳,直接使用sql 查詢 * @parem $level 當前id所在層級,默認2 * */ function getParent($id_pid,$array=array(), $level = 2) { $f_name=__FUNCTION__; // 定義當前函數名 static $list=array(); //$array=Db::table('table_name')->where('id',$id_pid)->select(); TP5 foreach($array as $k=>$v) { if($v['id']== $id_pid) { //父級分類id等於所查找的id $flg = str_repeat('|--',$level); // 更新 名稱值 $v['n'] = $flg.$v['n']; // 輸出 名稱 echo $v['n']."<br/>"; $list[]=$v;
// 刪除數組
unset($array[$k]); if($v['pid']>=0) { $f_name($v['pid'],$array,$level-1); } } } return $list; } // 調用 getParent(10,$array, $level = 3); echo "<hr/>"; getParent(8,$array, $level = 3);
調用結果顯示
getParent(10,$array, $level = 3); |--|--|--永年區鎮 |--|--永年區 |--邯鄲市 ----------------------------------------- getParent(8,$array, $level = 3); 河北省 |--|--|--永年區 |--|--邯鄲市 |--河北省
根據父id獲得所有下級子類數
/**根據指定id 查詢,所有的子節
* @parem $id 要查詢的id
* @parem $array 查分類的數據,在項目使用中此參數可以不傳,直接使用sql 查詢
* @parem $level 層級,默認1 * */ function getSon($id,$array=array(),$level=1) { $f_name=__FUNCTION__; // 定義當前函數名 static $list; //$array=Db::table('table_name')->where('pid',$id)->select(); TP5 foreach ($array as $k => $v) { if($v['pid'] == $id) { $flg = str_repeat('|--',$level); // 更新 名稱值 $v['n'] = $flg.$v['n']; // 輸出 名稱 echo $v['n']."<br/>"; //存放數組中 $list[] = $v;
// 刪除查詢過的數組
unset($array[$k]); $f_name($v['id'],$array,$level+1); } } return $list; }
// 調用 $list=$f_name(1,$array);
調用結果:
|--邯鄲市 |--|--永年區 |--|--|--永年區鎮 |--武安市
