PHP递归函数从平面表中检索分层数据(Zend Framework)

时间:2010-03-03 16:03:19

标签: php mysql zend-framework recursion

我正在尝试从表中检索分层数据,但我没有这样做。该表具有(现在)以下列:ifc_key,ifc_name,ifc_parent。不使用ifc_key。 (主键,但不用于此功能。

目的是获得一个数组。每个元素都是“父”接口。 (所以这些根元素都是没有设置ifc_parent的ifc_name值(如果设置则等于ifc_name)。

考虑以下布局(演示):

  

ifc_key | ifc_name | ifc_parent
  0 | parent_ifc |
  1 | a0a | parent_ifc
  2 | a0b | parent_ifc
  3 | b0a | VIF1
  4 | b0b | VIF1
  5 | vif1 | a0a

所以我正在寻找的数组是从查询生成的:

Array
(
[parent_ifc] => Array
    (
        [a0a] => Array
            (
                [vif1] => Array
                    (
                        [0] => b0a
                        [1] => b0b
                    )

            )

        [a0b] => 
    )
)  

我提出的功能在本段下面。我想创建一个递归函数,它在查找子项时调用自己,但问题是在第一次调用此方法时没有选择任何子项。 (空父母的父母都是父母)。所以我只让父母回来,但没有一个孩子(可能还有他们的孩子等等 - 理论上这可能是无限期的。)

public static function getByFilerOrganisedChildren($filer_id, $parent = '')
{
    $table   = new Filer_Interface_Table();
    $where[] = $table->getAdapter()->quoteInto('ifc_system_id = ?', $filer_id);
    $where[] = $table->getAdapter()->quoteInto('ifc_parent = ?', $parent);
    $rows    = $table->fetchAll($where, 'ifc_parent ASC');

    foreach ($rows as $row) {
        if ($row->ifc_parent == '') $data[] = $row->ifc_name;
        else {
            $data[$row->ifc_parent][] = $row->ifc_name;
            self::getByFilerOrganisedChildren($filer_id, $row->ifc_parent);
        }
    }

    return (isset($data) ? $data : false);
}

5 个答案:

答案 0 :(得分:2)

您在方法之前未提及ifc_system_id列,因此我认为这与问题无关。您指定为期望的输出实际上也是不一致的。

您似乎缺少的关键是使用与子记录相关的数据调用递归函数 - 在本例中为ifc_name而不是ifc_parent

public function getByFilerOrganisedChildren($filer_id, $parent = '')
{
    $table   = new Filer_Interface_Table();
    $where[] = $table->getAdapter()->quoteInto('ifc_system_id = ?', $filer_id);
    $where[] = $table->getAdapter()->quoteInto('ifc_parent = ?', $parent);
    $rows    = $table->fetchAll($where, 'ifc_parent ASC');

    $data = array();
    foreach ($rows as $row) {
        $data[$row->ifc_name] = $this->getByFilerOrganisedChildren($row->ifc_name);
    }

    return (! empty($data) ? $data : false);
}

答案 1 :(得分:0)

你能写下你如何称呼这个功能吗?有什么参数? 而且我认为你必须为你的类提供$ data私有静态字段

答案 2 :(得分:0)

我这里没有回答你的问题,但是:这不是在数据库中存储分层数据的非常有效的方法

我宁愿推荐嵌套集(例如,在Doctrine ORM和Zend Framework [提案]中有简单的实现)。

您也可以尝试使用this article中描述的替代方法(波兰文,但提供的SQL和PHP示例是通用的)。

答案 3 :(得分:0)

public static function getByFilerOrganisedChildren($filer_id, $parent = '')
{
    $table   = new Filer_Interface_Table();
    $where[] = $table->getAdapter()->quoteInto('ifc_system_id = ?', $filer_id);
    $where[] = $table->getAdapter()->quoteInto('ifc_parent = ?', $parent);
    $rows    = $table->fetchAll($where, 'ifc_parent ASC');

    foreach ($rows as $row) {
        $data[$row->ifc_name] = array();
        /* self::getByFilerOrganisedChildren($filer_id, $row->ifc_name); */
    }

    Zend_Debug::dump($data);

    return (isset($this->data) ? $this->data : false);
}  

使用上面的注释行,Zend_Debug :: dump()的输出是:

  

阵列(7){
   [“cifs-80”] =>数组(0){
   }
   [“e0M”] =>数组(0){
   }
   [“lo”] =>数组(0){
   }
   [“vif1”] =>数组(0){
   }
   [“vif1-81”] =>数组(0){
   }
   [“vif1-82”] =>数组(0){
   }
   [“vif1-83”] =>数组(0){
   }
  }

这些都是“父母”。但正如预期的那样(因为对表的调用是“ifc_parent =''”),所有子项(及其可能的子项)都不会被返回。

然而,当我取消注释该行时:

self::getByFilerOrganisedChildren($filer_id, $row->ifc_name);  

输出结果为:

NULL  

我想这是因为:

abstract class Filer_Interface_Abstract extends Filer_Db_Class  

但我无法改变这一点 - 因为它是当前应用程序的构建方式。建议?

答案 4 :(得分:0)

我的代码

DB计划:

create table roles (
    id      int not null auto_increment,
    name    varchar(50) UNIQUE not null,
    inherit_id  int
)

PHP代码:

class Default_Model_Roles extends Zend_Db_Table_Abstract {

   protected $_parents = array();

    public function getParents($id) {
        $this->_getAllParents($id);
        return (! empty($this->parents) ? $this->parents : FALSE);
    }

    public  function _getAllParents($id) {
        $select = $this->select();
        $select->where('id = ?', $id)
           ->order('id');
        $row = $this->fetchRow($select);
        $this->parents[] = $row->id;
        if ($row->inherit_id != NULL)   
            $this->_getAllParents($row->inherit_id);
    }
}

使用:

$table = new Default_Model_Roles();
$parents = $table->getParents($this->role_id);