【PHP】閉包テーブル

書籍『SQLアンチパターン』の閉包テーブルについて
基本的な思想とかはググればある、実装がなかなか見つからなかったので記す。
PHPとAjaxを想定

テーブル

# コメント用テーブル
CREATE TABLE `Comments` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `parent_id` int(11) NOT NULL DEFAULT 0, # 返信先のコメントid
  -- `blog_id` int(11) NOT NULL,
  `author` varchar(255),
  `body` TEXT,

  PRIMARY KEY (`id`)
  -- FOREIGN KEY (`blog_id`) REFERENCES `Blog` (`id`)
  ) ENGINE=InnoDB DEFAULT CHARSET=utf8;

# コメント関連テーブル
CREATE TABLE `TreePaths` (
  `ancestor` int(11) NOT NULL, # 祖先
  `descendant` int(11) NOT NULL, # 子孫

  PRIMARY KEY (`ancestor`,`descendant`),
  KEY `descendant` (`descendant`),
  FOREIGN KEY (`ancestor`) REFERENCES `Comments` (`id`),
  FOREIGN KEY (`descendant`) REFERENCES `Comments` (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

INSERT INTO `Comments` (`id`, `parent_id`, `author`, `body`) VALUES
 (1, 0, "Aくん", "コメント1"), (2, 1, "Bくん", "コメント2"), (3, 1,"Cさん", "コメント3"), (4, 3, "Dさん", "コメント4"),
 (5, 1, "Eさん", "コメント5"), (6, 5, "Fさん", "コメント6"), (7, 6, "Gさん", "コメント7"), (8, 5, "Hさん", "コメント8");

INSERT INTO `TreePaths` (`ancestor`, `descendant`) VALUES (1, 1), (1, 2), (1, 3), (1, 4), (1, 5), (1, 6), (1, 7), (1, 8),(2, 2), (3, 3), (3, 4), (4, 4), (5, 5), (5, 6), (5, 7), (5, 8),(6, 6), (6, 7), (7, 7), (8, 8);

php

jsonを吐く、だけ

<?php
$dbh = new PDO('mysql:dbname=closure_parent; host=localhost;unix_socket=/Applications/MAMP/tmp/mysql/mysql.sock; charset=utf8;', 'root', 'root');

$sql = "SELECT c.* FROM Comments AS c
  INNER JOIN TreePaths AS t ON c.id = t.descendant
WHERE t.ancestor IN (
  SELECT c2.id FROM Comments AS c2 WHERE parent_id = 0
);";
prepare($sql);
$stmt->execute();
$rows = $stmt->fetchAll(PDO::FETCH_ASSOC);


function exhtmlspecialchars($val) {
    if (is_array($val)) {
        return array_map("exhtmlspecialchars", $val);
    } else {
        return htmlspecialchars($val, ENT_QUOTES);
    }
}

$res = exhtmlspecialchars($rows);

echo json_encode($rows, JSON_UNESCAPED_UNICODE);

HTML

ajaxで受け取ってフロントで適当に、綺麗じゃないので核のとこだけ

 :

for(var jid in json){
    var obj = json[jid]

    var text = "<ul id='"+ comid + obj.id +"'><li>"+ obj.author +"</li><li>"+ obj.body +"</li></ul>";
    console.log(text);

    if(obj.parent_id === "0"){
        console.log(obj)
        $("div#comments").append(text);
        $("div#comments").val("hoge");

        continue;
    }

    $("ul#"+ comid + obj.parent_id).append("<li>"+ text +"</li>");

}

 :

所感

commentsテーブルにparent_idを追加するのはアンチパターンだと書籍に記されていたので追加しないことを前提に考えてしまった
閉包テーブル+parent_idでフロントサイドも楽に実装

これからReact+Fuelで書き直す

コメントを残す

以下に詳細を記入するか、アイコンをクリックしてログインしてください。

WordPress.com ロゴ

WordPress.com アカウントを使ってコメントしています。 ログアウト /  変更 )

Google フォト

Google アカウントを使ってコメントしています。 ログアウト /  変更 )

Twitter 画像

Twitter アカウントを使ってコメントしています。 ログアウト /  変更 )

Facebook の写真

Facebook アカウントを使ってコメントしています。 ログアウト /  変更 )

%s と連携中