通过相关实体正确递归

时间:2011-10-20 16:18:48

标签: php json recursion visualization

我有一组组织及其董事会成员。 所有组织都有董事会成员,许多董事会成员都是不止一个组织的董事会成员。

我使用JIT Hypertree来说明他们的关系。 JIT Hypertree架构要求一个项目是所有项目的父项,并且基于单个JSON数组绘制。

我希望能够重新定位事件查询并根据更改重新填充图表。那么2个级别就可以了,但我还没有弄清楚如何做到这一点。

我目前的代码从初始组织手动递归三级,但我想要的是重新诅咒所有相关记录。

所以它将从一个Org开始并添加Org的一系列孩子(董事会成员)。然后获取每个董事会成员的所有董事会(当前Org除外)并将其添加为董事会成员的子女。

这将一直持续到每条线索死亡 - 大概是一个只属于一个董事会的董事会成员。

任何人都有关于如何创建此数组并避免重复的建议吗?

$board = $center->board();

$top['id'] = $center->ID;
$top['name'] = $center->Org;
$top['children'] = array();
if ($board) {
    foreach ($board as $b) {
        $child['id'] = $b->ID;
        $child['name'] = (strlen(trim($b->Last)) > 0) ? $b->First . ' ' . $b->Last : 'Unknown';
        $child['data']['orgname'] = $center->Org;
        $child['data']['relation'] = $b->Role;
        $child['data']['occupation'] = $b->Occupation;
        $child['children'] = array();
        $childboards = $b->boards();
        if ($childboards) { foreach ($childboards as $cb) { 
            $gchild['id'] = $cb->ID;
            $gchild['name'] = $cb->Org;
            $gchild['data']['orgname'] = (strlen(trim($b->Last)) > 0) ? $b->First . ' ' . $b->Last : 'Unknown';
            $gchild['children'] = array();
            $childboardmembers = $cb->board();
            if ($childboardmembers) { foreach ($childboardmembers as $cbm) {
                $ggchild['id'] = $cbm->ID;
                $ggchild['name'] = (strlen(trim($cbm->Last)) > 0) ? $cbm->First . ' ' . $cbm->Last : 'Unknown';
                $ggchild['data']['orgname'] = $cb->Org;
                $ggchild['data']['relation'] = $cbm->Role;
                $ggchild['data']['occupation'] = $cbm->Occupation;
                $ggchild['children'] = array();
                $gchild['children'][]= $ggchild;
            }}
            $child['children'][]= $gchild;
        }}
        $top['children'][] = $child;
    }
} 
$top['data'] = array();
$top['data']['description'] = $center->Desc;
echo json_encode($top);

//编辑2011.10.24在Re hakre回复中 我的数据结构是具有唯一ID的组织表,具有唯一ID的人员表,然后是两个指定组织(实体)和人员以及人员在实体中扮演的角色的桥接表。典型的多对多。根本没有子板。我制作了一个现在看起来毫无意义的图像,但我会将它添加到底部。

JIT库数据结构对我来说有点疯狂,因为它在他们的乐队示例中是这样的:

Top: Nine Inch Nails
  Child: Jerome Dillon
    Child:  Howlin Maggie (another band)
      {all the bands' members and then all of their bands...}

因此组织(乐队)被视为一个人,即使它由一些人组成。当我使用上面的代码进行递归时,我得到(我认为)可怕的臃肿,但它使得JSON尽管膨胀而正常工作。

示例JSONExample Visualization //结束编辑

schema

3 个答案:

答案 0 :(得分:2)

您的问题很难回答,因为您的数据结构主要是未知的。

对于图形表示,如果我理解正确,您只需要提供简单的关系:

*- Parent
   +- Child
   +- Child
   ...
   `- Child

您的数据结构有不同的格式,我不知道具体,但它类似于:

Org <-- 1:n --> Board

Board <-- n:n --> Board # If you have sub-boards

Board <-- n:n --> Member

无论您的数据是什么表示,要将数据映射或转置到图形表示所需的结构上,您都需要一些能够处理这些数据的函数。

为此,您需要在两者和特定键之间共享分类/类型,以便您可以从事件中查找所需的数据以返回数据。例如:

if (request_parent_is_org())
{
    $id = request_parent_id();
    $parent = data_get_board($id);
    $parent->addChildrent(data_get_board_children($id));
}
else
{
    ... # All the other decisions you need to take based on request type
}

view_response_to_json($parent);

答案 1 :(得分:2)

您的多对多数据模型的内容是graph。 JIT专为trees而设计。

换句话说,只要一个人连接到多个组织,JIT就无法正确显示数据中表示的交叉线。

我建议使用正确的网络图形可视化 - D3.js为现代浏览器提供了很好的实现。

它使用的JSON数据格式实际上更容易实现给定您的表结构 - 对于所有组织和人员,您定义对象:

{
    "name": "Mme.Hucheloup",
    "group": 1
},
{
    "name": "Afton School Board",
    "group": 2
}

对于关联表中的每个关联,您可以定义将它们连接在一起的连接对象:

{
    "source": 1,
    "target": 2
},

D3中的花式编码负责其余部分。祝你好运!

答案 2 :(得分:2)

您可以使用以下功能:

function get_orgs_and_childs ($child_id, $found = array()) 
{
    array_push ($found, $child['name']);

    if($child['children'])){
            $found[] = get_parents($child['id'], $found);
    }
    return $found;
}

使用以下方式调用:

$orgs = get_orgs_and_childs($child['id']);