PHP在無限分類時注意的一些問題(不保證代碼徹底正確哦)

(注意:代碼使用的是原生PHP,旨在提供解決思路)
1 無限分類的查找(獲取全部節點)

代碼:php

/**
 * 無限分類查詢,默認 pid 爲 0
 * @param $pid
 * @return array $res
 */
protected function selectTree($pid = 0)
{
    $res = [];
    $sql = "SELECT * FROM " . $this->tbname . " WHERE pid=" . $pid;
    $result = @mysqli_query($this->link, $sql);
    if ($result) {
        $count = mysqli_num_rows($result);
        if ($count > 0) {
            while ($rows = mysqli_fetch_assoc($result)) {
                $rows['children'] = $this->selectTree($rows['id']);
                $res[] = $rows;
            }
        }
        mysqli_free_result($result);
    }
    return $res;
}

 

2 無限分類節點的刪除,不能單純地刪除當前節點,須要查找到當前節點下的全部子節點,一併刪除

代碼:前端

/**
 * 刪除目錄樹
 * @param $id
 */
protected function deleteTree($id)
{
    $res = $this->selectTree($id);
    if (!empty($res)) {
        foreach ($res as $v) {
            $this->deleteTree($v['id']);
        }
    }
    $sql = "DELETE FROM " . $this->tbname . " WHERE id=" . $id;
    mysqli_query($this->link, $sql);
}
3 **無限分類的編輯,因爲在編輯的時候其父級是可選擇的,因此有可能形成用戶選擇到當前節點的子節點(),因此要進行判斷。雖然說是無限分類,但正常狀況下目錄深度是會有限度的,若是給定了目錄深度,還要判斷選擇父級以後的目錄深度是否超出範圍。

若是將編輯的元素放在其子元素下,所形成的問題:在查詢的時候無限循環!!mysql

idsql

pid框架

namefetch

1this

0spa

test1orm

2遞歸

1

test2

修改以後:

id

pid

name

1

2

test1

2

1

test2

如上表所示,在進行無限分類查詢時,就會陷入死循環!

因此,針對可能會出現的問題,給出下面的解決辦法,在用戶修改時進行判斷,經過則能夠修改,未經過則給出提示。

3.1 判斷用戶選擇的是不是當前節點(這個只須要判斷選擇的節點和當前編輯節點的ID是否相同便可)

3.2 判斷用戶選擇的是不是子節點(若是是的話返回true   

 

/**
 * 判斷id所對應的元素是不是pid所對應元素的子元素,是的話返回true
 * @param $id
 * @param $pid
 * @return boolean $result
 */
protected function isChild($id, $pid)
{
    $result = false;
    $sql = "SELECT pid FROM " . $this->tbname . " WHERE id=" . $id;
    $res = @mysqli_query($this->link, $sql);
    if ($res) {
        while ($rows = mysqli_fetch_assoc($res)) {
            $result = ($pid === $rows['pid']) ? true : (($rows['pid'] !== 0) ? $this->isChild($rows['pid'], $pid) : false);
        }
    }
    return $result;
}

3.3 判斷用戶選擇的節點是否已經達到目錄深度

在作完後面的一步以後,這一步就比較好實現了:

/**
 * 判斷所選元素是否達到目錄深度,達到返回true
 * @param $id
 * @return mixed
 */
protected function isMaxDeep($id)
{
    return $this->deepUp($id) >= $this->maxDeep;
}

3.4 判斷修改以後的目錄深度是否超出限定範圍

 

/**
 * 修改以後的最終深度,若是深度大於規定深度,返回true
 * @param $pid
 * @param $id
 * @return mixed
 */
protected function lastDeep($pid, $id)
{
    return ($this->deepUp($pid) + $this->deepDown($id)) > $this->maxDeep;
}

/**
 * 向上查找父元素的深度
 * @param $id
 * @param int $k
 * @return int
 */
protected function deepUp($id, $k = 1)
{
    $sql = "SELECT pid FROM " . $this->tbname . "WHERE id=" . $id;
    $res = @mysqli_query($this->link, $sql);
    if ($res) {
        while ($rows = mysqli_fetch_assoc($res)) {
            ($rows['pid'] !== 0) && $k = $this->deepUp($rows['pid'], $k+1);
        }
    }
    return $k;
}

/**
 * 向下查找子元素的深度
 * @param $id
 * @param int $k
 * @return int
 */
protected function deepDown($id, $k = 0)
{
    $sql = "SELECT * FROM " . $this->tbname . "WHERE pid=" . $id;
    $res = @mysqli_query($this->link, $sql);
    if ($res && mysqli_num_rows($res) > 0) {
        $k++;
        while ($rows = mysqli_fetch_assoc($res)) {
            $k = max($k, $this->deepDown($rows['id'], $k))
        }
    }
    return $k;
}

通過上面的判斷以後,根據返回的結果就能判斷是否能夠修改,若是返回true,則不能夠修改,若是是false則能夠進行修改。

(若是不用無限分類查詢,只是普通的查詢,讓前端去實現結果的顯示會怎麼樣呢??不懂那些框架是怎麼實現的,感受也是在用遞歸)

相關文章
相關標籤/搜索