PDO递归查询

时间:2015-03-31 19:53:03

标签: php mysql recursion pdo

我发现这个similar question虽然我无法绕过所选择的答案,或者确定它是否适用于我的情况。

我有一个图片库的下表:

CREATE TABLE image_categories (
  cat_id INTEGER UNSIGNED NOT NULL AUTO_INCREMENT,
  parent_id INTEGER UNSIGNED DEFAULT NULL,
  title VARCHAR(100) NOT NULL,
  valid TINYINT(1) UNSIGNED NOT NULL DEFAULT 1,

  PRIMARY KEY(cat_id),
  FOREIGN KEY (parent_id)
    REFERENCES image_categories(cat_id)
);

CREATE TABLE image_gallery (
  img_id INTEGER UNSIGNED NOT NULL AUTO_INCREMENT,
  cat_id INTEGER UNSIGNED NOT NULL,
  fname CHAR(45) NOT NULL,
  title VARCHAR(100) DEFAULT NULL,
  description VARCHAR(256) DEFAULT NULL,
  create_date DATETIME NOT NULL,
  valid TINYINT(1) UNSIGNED NOT NULL DEFAULT 1,

  PRIMARY KEY(img_id),
  FOREIGN KEY (cat_id)
    REFERENCES image_categories(cat_id)
);

与文件树目录类似,类别就像文件夹一样,它们可以有子项,而这些子项可以有更多的子项创建无限层次结构。

鉴于具体cat_id我可以按如下方式提取图像:

$sql = "SELECT * FROM image_gallery WHERE cat_id = :cat_id AND valid = TRUE";
$sth = $this->db->prepare($sql);
$sth->execute(array(':cat_id' => $cat_id));

$images = array();
while ($row = $sth->fetch(PDO::FETCH_ASSOC)) {
    $images[$row['img_id']]['cat_id'] = $row['cat_id'];
    $images[$row['img_id']]['fname'] = $row['fname'];
    $images[$row['img_id']]['title'] = $row['title'];
    $images[$row['img_id']]['description'] = $row['description'];
    $images[$row['img_id']]['create_date'] = $row['create_date'];
    $images[$row['img_id']]['valid'] = $row['valid'];
}

然而,除了任何子类别之外,我还想提取指定类别的图像,直到找不到更多的子类别。

如何实现这些结果?是使用修改过的查询还是某种类型的递归函数?

1 个答案:

答案 0 :(得分:1)

您必须检查代码,但是这样的内容可以让您显示父类别的图像。首先,将所有相关的类别ID保存到数组中:

function get_cat_id($parent_id) {
    $sql = "SELECT cat_id FROM image_categories WHERE parent_id = :parent_id AND valid = TRUE";
    $sth = $this->db->prepare($sql);
    $sth->execute(array(':parent_id' => $parent_id));

    $category = $sth->fetch(PDO::FETCH_ASSOC);

    if ($sth->rowCount() > 0) {
        return $category['cat_id'];
    } else {
        return FALSE;
    }
}

$cat_ids = array();
$parent_id = $cat_id; /* This is the $cat_id you are using now... */
while ($cat_id = get_cat_id($parent_id)) {
    $cat_ids[] = $cat_id;
    $parent_id = $cat_id;
}

然后,修改您的SQL查询(您可以在此处查看示例PHP - Using PDO with IN clause array):

$in = str_repeat('?,', count($cat_ids) - 1) . '?'; 
$sql = "SELECT * FROM image_gallery WHERE cat_id IN ($in) AND valid = TRUE";
$sth = $this->db->prepare($sql);
$sth->execute($cat_ids);

$images = array();
while ($row = $sth->fetch(PDO::FETCH_ASSOC)) {
    $images[$row['img_id']]['cat_id'] = $row['cat_id'];
    $images[$row['img_id']]['fname'] = $row['fname'];
    $images[$row['img_id']]['title'] = $row['title'];
    $images[$row['img_id']]['description'] = $row['description'];
    $images[$row['img_id']]['create_date'] = $row['create_date'];
    $images[$row['img_id']]['valid'] = $row['valid'];
}

编辑:抱歉,我的代码只会抱怨一个子类别。只需用此代码替换函数get_cat_id和while循环即可。我测试它,我认为它可能会起作用:

function get_subcategories($parent_id) {
    global $cat_ids;

    $sth = $this->db->prepare($sql);
    $sth->execute(array(':parent_id' => $parent_id));
    $categories = $sth->fetchAll(PDO::FETCH_ASSOC);

    foreach ($categories as $category) {
        $cat_ids[] = $category['cat_id'];
        get_subcategories($category['cat_id']);
    }   
}

 /* This is the $cat_id you are using now... */
$cat_ids = array($cat_id);
get_subcategories($cat_id);

其余代码(IN子句)不会改变。