0

やあ、

sqlite-table にツリー構造のデータがあり、php で再帰的に削除したいと考えています。データは次のようになります。

ID 親 ID
0 -1
1 0

関数:

/**
 * Delete a category with all it's subcategories
 * 
 * @param {number} id The id of the category which should be deleted
 * @return {number} The number of categories deleted
 * @throws {Exception} Throws an exception with some description text if anything goes wrong
 */
public function deleteCategory($id) {
    static $catCnt = 0;

    Helper::log("deleteCategory: id = $id");

    try {
        // Open database-connection
        $this->openDatabase();

        // Remove all subcategories recursively
        $stmtSubs = $this->_db->prepare("SELECT Id FROM categories WHERE ParentId = :id");
        $stmtSubs->bindParam(":id", $id, PDO::PARAM_INT);
        $stmtSubs->execute();
        while ($row = $stmtSubs->fetch(PDO::FETCH_ASSOC)) {
            Helper::log("deleteCategory: call recursively to delete subcategory with id = " . $row["Id"]);
            $this->deleteCategory($row["Id"]);
        }

        // All subcategories have been removed -> Now it's time to remove the category itself
        $stmt = $this->_db->prepare("DELETE FROM Categories WHERE Id = :id");
        $stmt->bindParam(":id", $id, PDO::PARAM_INT);

        Helper::log("deleteCategory: before execution, id = $id");
        $stmt->execute();

        // The code from here on never gets executed...
        Helper::log("deleteCategory: after execution, id = $id");

        $catCnt += $stmt->rowCount();

        return $catCnt;
    } catch (Exception $ex) {
        throw new Exception("Deletion of category failed:<br>" . $ex->getMessage());
    }
}

この関数をパラメーター 0 で呼び出すと、次の出力が得られます。

31.08.2012 09:39:58: deleteCategory: id = 0
31.08.2012 09:39:58: deleteCategory: call recursively to delete subcategory with id = 1
31.08.2012 09:39:58: deleteCategory: id = 1
31.08.2012 09:39:58: deleteCategory: before execution, id = 1
// Here should be the "after execution"-entry, but instead it "waits" half a minute and starts the whole execution from the beginning...
31.08.2012 09:40:28: deleteCategory: id = 0
31.08.2012 09:40:44: deleteCategory: call recursively to delete subcategory with id = 1
31.08.2012 09:40:44: deleteCategory: id = 1
31.08.2012 09:40:44: deleteCategory: before execution, id = 1

ご覧のとおり、ID 1 のサブカテゴリを実際に削除するまでは問題なく実行されます。execute-command は終了せず、代わりに 30 分何もしないように見え、その後、 ID 0 から始まります。

2回目の「試行」の後、内部サーバーエラーが返されます(「サーバーで内部エラーまたは構成ミスが発生し、リクエストを完了できませんでした...」)

この関数をパラメーター 1 で呼び出すと、再帰が呼び出されないため、すべて正常に機能します。

ここで何が起きてるの?

ありがとう、

ミク

4

1 に答える 1

0

半日のようにこれに苦労し、ここに投稿することを決定し、ここに投稿し、投稿直後にもう一度見て、問題を見ました:

「$this->openDatabase();」の再帰呼び出し すべての悪の源でした...

ありがとう ;)

于 2012-08-31T08:10:09.013 に答える