循环“步骤”,然后“子步骤”,然后在PHP / CodeIgniter中“子子步骤”

时间:2010-12-28 15:20:11

标签: php codeigniter codeigniter-datamapper

我想我的第一个问题是,因为我是唯一的开发人员,所以我很想让其他人抛出想法,或者在我遇到问题时得到想法。是否有专门解决该问题的网站?像一个虚拟的共同程序员网站?或者StackOverflow可以这样工作吗?

我的主要问题:我正在处理类似“待办事项”列表的事情,但每个项目可能都有子步骤......甚至是子步骤......甚至可能更进一步。我有一个包含字段“id,item,parent_id”的表,所有顶级项目的parent_id = 0.在CodeIgniter中使用Datamapper ORM,我正在使用它:

$i = new Item();
$i->where('parent_id',0)->get();
foreach($i as $item) {
   echo $item->item;
   $si = new Item();
   $si->where('parent_id',$item->id)->get();
   foreach($si as $subItem) {
      echo $subItem->item;
      // and so on
   }
}

它有效,但有没有更聪明的方法来实现这一目标?某种递归函数可能吗?

我也在努力让所有人都能管理其他人,这样他们就可以将物品拖放到他们需要去的地方......但这是另一天的另一个问题。

3 个答案:

答案 0 :(得分:3)

如果您编写自己的SQL,可以在3个查询中执行此操作。

"SELECT * FROM items WHERE parent_id = 0;"
"SELECT * FROM items WHERE parent_id IN (SELECT id FROM items WHERE parent_id = 0;"

但是,您看起来想要一个多嵌套的tree-like structure

| item |
  | sub-item |
    | sub-sub-item |

如果您正在使用CI,那么(我认为)更好的ORM称为Doctrine,它将处理自引用树状数据结构(使用您建议的递归)。值得庆幸的是,有一篇很好的文章可以将它合并到CodeIgniter中!

http://www.phpandstuff.com/articles/codeigniter-doctrine-from-scratch-day-1-install-and-setup

Doctrine将为您构建查询 - 它还支持关系和许多其他方便的功能,如CodeIgniter缺少的缓存:)

答案 1 :(得分:3)

如果我是你,我会考虑实现树结构。你基本上已经为这里的邻接列表设置了基础(从数据库的角度来看 - 你仍然需要编写和测试的PHP代码)。如果添加level列来定义任何给定任务在其层次结构中的级别,则可以通过自联接使用1-2个查询来提取所有数据,但如果嵌套级别非常深,这将会很慢。 / p>

另一种方法是使用嵌套集和预订树遍历,这是一项更多的工作,特别是考虑到你似乎不需要每个节点有多个分支。

看一下Managing Hierarchical Data in MySQL,它从数据库方面详细解释......它是MySQL特定的,但你应该能够以数据库不可知的方式应用相同的原则,或者用于另一个特定的数据库。

当然,无论你需要在PHP方面实现这种映射,这种方式都比你现在做的更多......但是它也可以让你更少地点击数据库。

我还建议使用Doctrine(也就是Seth也推荐)而不是CI Datamapper ...它已经实现了所有这些...你只需要学习Doctrine的基础知识并将它挂钩到CI我确定有很多教程。

答案 2 :(得分:0)

像这样的Smth,没有经过测试:count($ ss)可能不会返回一个好的值来查看是否有任何结果从查询返回所以请更新为必要的(在Zend中我可以依靠Zend_Db_Table_Rowset而不是shure什么对象CI返回,如果你可以计算结果的数量)请更新if语句只有在你的查询返回结果时调用该函数

    function recursive( $i )
    {
        foreach ( $i as $item )
        {
            echo $item->item;
            $si = new Item();
            $ss = $si->where('parent_id', $item->id)->get();
            if ( count($ss) > 0 ) 
                recursive($ss);
        }
    }
    $i = new Item();
    recursive($i->where('parent_id', 0)->get());