Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/mysql/62.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
PHP/MySQL/???-组织文章和任意深度的子文章,其中可以检索任何文章以及所有父级和子级_Php_Mysql_Sql_Relational Database_Hierarchical Data - Fatal编程技术网

PHP/MySQL/???-组织文章和任意深度的子文章,其中可以检索任何文章以及所有父级和子级

PHP/MySQL/???-组织文章和任意深度的子文章,其中可以检索任何文章以及所有父级和子级,php,mysql,sql,relational-database,hierarchical-data,Php,Mysql,Sql,Relational Database,Hierarchical Data,我将有一个文章或页面的数据库,有点像维基页面。所有文章名称都必须是唯一的,就像wiki页面一样。它们将被组织在一个灵活的深度层次结构中,每个文章都可以是多个其他文章的子文章或父文章——所有类别都由文章表示 用户应该能够直接跳转到任何页面——可能通过键入其唯一名称(输入主页上的框或domain.com/articles/name),或者搜索并选择结果,或者单击另一篇文章中的链接。但是,他们还应该能够深入到各个类别,当前文章所属的所有类别都可以看到面包屑(一般不应该超过2或3个),并且能够查看所有(

我将有一个文章或页面的数据库,有点像维基页面。所有文章名称都必须是唯一的,就像wiki页面一样。它们将被组织在一个灵活的深度层次结构中,每个文章都可以是多个其他文章的子文章或父文章——所有类别都由文章表示

用户应该能够直接跳转到任何页面——可能通过键入其唯一名称(输入主页上的框或domain.com/articles/name),或者搜索并选择结果,或者单击另一篇文章中的链接。但是,他们还应该能够深入到各个类别,当前文章所属的所有类别都可以看到面包屑(一般不应该超过2或3个),并且能够查看所有(或尽可能多的)子文章

例如,可能有:

    • 男性
      • 鲍勃
      • 吉姆
    • 女性
      • 爱丽丝
      • 萨莉
    • 雇员
      • 鲍勃
      • 萨莉
  • 食物
    • 食物
      • 小吃
        • 筹码
          • 食盐和醋
          • 酸奶油和洋葱
        • 爆米花
      • 披萨
      • 寿司
      • 苏打水
        • 可乐
        • 根啤酒
      • 果汁
        • 苹果汁
        • 橙汁
        • 葡萄汁
例如,如果有人转到Bob的页面,他们将看到关于Bob的所有信息,以及:

Parents:
Articles > People > Male > (Bob)
Articles > People > Employees > (Bob)
Children:
(none)
Parents: 
Articles > Edibles > Food > (Snacks)
Children:
(Snacks) > Chips
(Snacks) > Chips > Salt & Vinegar
(Snacks) > Chips > Sour Cream & Onion
(Snacks) > Popcorn
如果有人进入小吃页面,他们会看到关于小吃的文章,以及:

Parents:
Articles > People > Male > (Bob)
Articles > People > Employees > (Bob)
Children:
(none)
Parents: 
Articles > Edibles > Food > (Snacks)
Children:
(Snacks) > Chips
(Snacks) > Chips > Salt & Vinegar
(Snacks) > Chips > Sour Cream & Onion
(Snacks) > Popcorn

我甚至不知道从哪里开始,这里。关于设置SQL表来实现这一点,我将面临什么样的噩梦?这些查询将是什么样子?我计划实现某种缓存,但我不想依赖它来提高性能。为了保证在共享主机上正常工作,并避免混淆数据库,我宁愿将所有这些都保存在MySQL或PostgreSQL中,这是站点其余部分所必需的。PHP将用于站点的其余部分,我想在有意义的时候将我能做的任何工作都转移到PHP中。如果另一种技术,比如非关系型数据库,可以让这变得非常简单,我也许可以使用它

我已经看到了第1条>第2条>第1条的问题导致了可怕的问题,但我认为不允许一篇文章将其祖先列为儿童没有任何害处


除了在一开始就试图找出如何实现这一切的帮助之外,我还遗漏了其他一些主要的陷阱吗?

这是非常琐碎的,真的,这是一个非常简单的问题。:)
此的表架构如下所示:

id            unique id, perhaps the unique name
parent_id     id of parent element
lft           MPTT left field
rght          MPTT right field
...           any other fields you like

INDEX UNIQUE(id)

就这样。每个项目只有一个父项目。顶部元素可以将
NULL
作为其父id,或者您将只有一个顶部节点具有
NULL
,所有其他项目都是其子项。那取决于你的喜好。这实际上就是您所需要的,但是为了简化记录的获取,您将在MPTT逻辑中使用
lft
rght
字段。阅读以了解它们的用途。使用这些字段,您还可以避免通过一次简单的检查将条目设置为自己子项的子项。

从数据库方面看,您的关系非常简单。像这样的事情会让你开始:

CREATE TABLE articles (id INT NOT NULL AUTO_INCREMENT PRIMARY KEY,
parent_id INT NOT NULL DEFAULT '0'
name VARCHAR(100) NOT NULL,
content TEXT);
现在你只需要决定在哪里执行“没有祖先作为孩子”的规则。如果要在数据库中强制执行该操作,可以编写一个插入/更新触发器,检查传入的父\u id是否已经是子代,如果已经是子代,则不允许该操作。在典型用法中,这永远不会发生,因为在PHP端,当您创建内容时,通常从父级开始,然后添加子级,而不会将父级添加到现有内容中

至于查找记录的祖先和子记录,最好是在PHP中使用基于以下查询的两个循环:

// The ancestors:
$sql = "SELECT * FROM articles WHERE id = {$currentRecord->parent_id}";

// The children:
$sql = "SELECT * FROM articles WHERE parent_id = {$currentRecord->id";

希望这能让您开始。

是的,我认为这是构建您的结构的最好、最简单的方法。如果您使用pear,那么您可以使用嵌套的集合包。您说“每篇文章都有一个且只有一个父文章”。这是否仍然允许任何项目可以包含在多个类别中(Bob包含在男性和员工中,并且可能也直接列在人中),并且具有多个子项链?还有,我怎样才能一次把一篇文章的所有孩子和家长都找来?+1,非常好地提到了MPTT。自从20年前我的高级数据结构课程开始,我就没有使用过它,但它的效率更高。@Eph不,那是不可能的。我在你的问题中没有看到你想那样做。如果这是一个要求,那么MPTT不适合你。我一直称之为邻接列表。MySQL网站上有一篇非常好的文章,但现在已经不存在了。我在这里找到了一份副本: