基于父ID处理的树结构库,例如自连接数据库表

2.1 2018-05-25 01:42 UTC

This package is auto-updated.

Last update: 2024-09-11 16:43:48 UTC


README

Build Status SensioLabsInsight

概述

此库提供使用父ID引用结构化处理数据的功能。一个典型的例子是关系数据库中的一个表,其中每个记录的“父”字段引用另一个记录的主键。当然,使用范围不仅限于数据库中来源的数据,可以是任何东西:你提供数据,库使用它,无论数据来自哪里以及如何处理。

重要的是要知道,此包创建的树结构是只读的:你不能用它来执行树节点的修改。如果你需要这样的库,你可能想看看nicmart/tree

另一方面,一个很好的事情是它相当快。这不仅仅意味着代码本身,还意味着构造函数接受简单创建的输入数据格式。例如,要从数据库内容创建一个树,只需要一个SELECT语句就足够了,不管树的深度有多深,即使有成千上万的节点。

安装

安装Tree的首选方式是通过Composer。为此,只需执行composer require bluem/tree(根据您的Composer安装,可能是“composer.phar”而不是“composer”),一切应该都能正常工作。或者您可以将"bluem/tree": "~2.0"手动添加到composer.json文件中的依赖项中,然后安装/更新依赖项。

或者,您可以使用git克隆仓库或下载标记的版本。

更新

由于此库使用语义版本控制,您在运行composer update时将获得修复和功能添加,但不会获得破坏API的更改。

使用方法

创建树

// Create the tree with an array of arrays (or use an array of Iterators,
// Traversable of arrays or Traversable of Iterators):
$data = [
    ['id' => 1, 'parent' => 0, 'title' => 'Node 1'],
    ['id' => 2, 'parent' => 1, 'title' => 'Node 1.1'],
    ['id' => 3, 'parent' => 0, 'title' => 'Node 3'],
    ['id' => 4, 'parent' => 1, 'title' => 'Node 1.2'],
];
$tree = new BlueM\Tree($data);

// When using a data source that uses different keys for "id" and "parent",
// or if the root node ID is not 0 (in this example: -1), use the options
// array you can pass to the constructor:
$data = [
    ['nodeId' => 1, 'parentId' => -1, 'title' => 'Node 1'],
    ['nodeId' => 2, 'parentId' => 1, 'title' => 'Node 1.1'],
    ['nodeId' => 3, 'parentId' => -1, 'title' => 'Node 3'],
    ['nodeId' => 4, 'parentId' => 1, 'title' => 'Node 1.2'],
];
$tree = new BlueM\Tree(
    $data,
    ['rootId' => -1, 'id' => 'nodeId', 'parent' => 'parentId']
);

使用新数据更新树

// Rebuild the tree from new data
$tree->rebuildWithData($newData);

检索节点

// Get the top-level nodes (returns array)
$rootNodes = $tree->getRootNodes();

// Get all nodes (returns array)
$allNodes = $tree->getNodes();

// Get a single node by its unique identifier
$node = $tree->getNodeById(12345);

获取节点的前辈、兄弟、子代、祖先和后代

// Get a node's parent node (will be null for the root node)
$parentNode = $node->getParent();

// Get a node's siblings as an array
$siblings = $node->getSiblings();

// Ditto, but include the node itself (identical to $node->getParent()->getChildren())
$siblings = $node->getSiblingsAndSelf();

// Get a node's preceding sibling (null, if there is no preceding sibling)
$precedingSibling = $node->getPrecedingSibling();

// Get a node's following sibling (null, if there is no following sibling)
$followingSibling = $node->getFollowingSibling();

// Does the node have children?
$bool = $node->hasChildren();

// Get the number of Children
$bool = $node->countChildren();

// Get a node's child nodes
$children = $node->getChildren();

// Get a node's ancestors (parent, grandparent, ...)
$ancestors = $node->getAncestors();

// Ditto, but include the node itself
$ancestorsPlusSelf = $node->getAncestorsAndSelf();

// Get a node's descendants (children, grandchildren, ...)
$descendants = $node->getDescendants();

// Ditto, but include the node itself
$descendantsPlusSelf = $node->getDescendantsAndSelf();

访问节点的属性

// Get a node's ID
$id = $node->getId();

// Get the node's hierarchical level (1-based)
$level = $node->getLevel();

// Access node properties using get() overloaded getters or __get():
$value = $node->get('myproperty');
$value = $node->myproperty;
$value = $node->getMyProperty();

// Get the node's properties as an associative array
$array = $node->toArray();

// Get a string representation (which will be the node ID)
echo "$node";

示例:与自连接数据库表一起使用

<?php

require 'vendor/autoload.php';

// Database setup (or use Doctrine or whatever ...)
$db = new PDO(...);

// SELECT the records in the sort order you need
$stm = $db->query('SELECT id, parent, title FROM tablename ORDER BY title');
$records = $stm->fetchAll(PDO::FETCH_ASSOC);

// Create the Tree instance
$tree = new BlueM\Tree($records);
...
...

运行测试

PHPUnit被配置为开发依赖项,因此运行测试只需要

  • composer install
  • ./vendor/bin/phpunit

如果您想看到TestDox输出或覆盖率数据,可以在phpunit.xml.dist<log>部分中取消注释的行。

版本历史

2.0 (2018-02-04)

  • BC中断:getAncestors()getAncestorsAndSelf()不再将根节点作为返回数组的最后一个项目。 解决方案:如果您需要它,自己添加。
  • BC中断:从getAncestors()中删除了参数。 解决方案:如果您之前作为参数传递了true,将其更改为getAncestorsAndSelf()
  • BC中断:从getDescendants()中删除了参数。 解决方案:如果您之前作为参数传递了true,将其更改为getDescendantsAndSelf()
  • BC中断:从getSiblings()中删除了参数。 解决方案:如果您之前作为参数传递了true,将其更改为getSiblingsAndSelf()
  • BC中断:BlueM\Tree\InvalidParentException移动到BlueM\Tree\Exception\InvalidParentException解决方案:更新命名空间导入。
  • 新增:添加了Tree::rebuildWithData()方法,用于使用新数据重建树。
  • 新增:TreeTree\Node实现JsonSerializable并提供默认实现,这意味着您可以轻松地将整个树或节点序列化为JSON。
  • 新增:树数据不再必须是 数组,而是必须是 可迭代对象,这意味着您可以传递一个 数组 或者实现 Traversable 接口的对象。此外,节点数据也不再必须是数组,也可以是实现 Iterator 接口的对象。这些更改应使使用库变得更加灵活。
  • 内部更改:将自动加载从 PSR-0 更改为 PSR-4,将源目录从 lib/ 重命名为 src/,将测试目录从 test/ 重命名为 tests/
  • 内部更改:代码现代化,现在需要 PHP >= 7.0

1.5.3 (2016-05-20)

  • 处理混合类型(字符串和整数)的 ID

1.5.2 (2016-05-10)

  • 在 Readme 中添加了关于 JSON 序列化的信息。没有代码更改。

1.5.1 (2016-01-16)

  • 从构造函数中的 build() 移除了多余的第二个参数

1.5 (2015-01-14)

  • 在 Tree 类中添加了 createNode() 方法,这使得可以使用 Node 子类的实例作为节点

1.4 (2015-01-07)

  • Node 类上添加了 getSiblingsAndSelf() 方法。
  • getSiblings() 的参数已弃用,将在版本 2 中删除

1.3 (2014-11-07)

  • Tree 类上添加了 getNodeByValuePath() 方法,可以用于根据任意属性的祖先值和节点值在树中找到深层嵌套的节点。(请参阅方法文档注释中的示例。)

1.2 (2014-10-14)

  • Node 类上实现了 __isset()__get()。这使得可以将节点传递给 Twig(或其他以类似方式处理对象属性的库),并且可以直观地访问节点的属性。
  • 改进了节点属性的忽略大小写的处理

1.1 (2014-09-24)

  • 添加了 getDescendantsAndSelf()
  • 添加了 getAncestorsAndSelf()
  • getDescendants()getAncestors() 的参数已弃用,将在版本 2 中删除
  • 添加了一个检查,以确保节点不使用自己的 ID 作为父 ID。如果出现这种情况,将抛出异常,而以前不会抛出。因此,这可能会破坏向后兼容性,但只有在数据不一致的情况下才会如此。

1.0 (2014-06-26)

  • 第一个公开版本

作者 & 许可证

此代码由 Carsten Blüm (www.bluem.net) 编写,并许可在 BSD 2-Clause 许可证下。