【问题标题】:Looping through "steps", then "sub-steps", then "sub-sub-steps" in PHP/CodeIgniter在 PHP/CodeIgniter 中循环遍历“步骤”,然后是“子步骤”,然后是“子子步骤”
【发布时间】:2010-12-28 15:20:11
【问题描述】:

我想我的第一个问题是,由于我是唯一的开发人员,我很想念别人在我遇到问题时提出想法或获得想法。有专门解决这个问题的网站吗?像一个虚拟的联合程序员网站?或者 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
   }
}

它有效,但有没有更聪明的方法来完成这个?可能是某种递归函数?

我还在努力让其他人管理所有内容,这样他们就可以将项目拖放到他们需要去的地方......但这完全是另一回事了。

【问题讨论】:

    标签: php codeigniter codeigniter-datamapper


    【解决方案1】:

    如果您编写自己的 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 缺乏的缓存 :)

    【讨论】:

    • 不幸的是,我对切换到 Doctrine 的项目太深了,但是阅读文档后,我意识到 Datamapper 可以做类似的事情。
    • 您会发现 CI 的数据映射器在大型项目中表现不佳且速度缓慢
    【解决方案2】:

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

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

    查看Managing Hierarchical Data in MySQL,它从数据库方面详细解释了这两者...它是特定于 MySQL 的,但您应该能够以与数据库无关的方式或其他特定数据库应用相同的原则。

    当然,无论哪种方式,您都需要在 PHP 端为此实现映射,这比您现在做的工作要多……但它也允许您访问数据库的次数更少。

    我还建议使用 Doctrine(Seth 也推荐)而不是 CI Datamapper...它已经实现了所有这些...您只需要学习 Doctrine 的基础知识并将其与 CI 挂钩即可'肯定有大量的教程。

    【讨论】:

    • 都是 mySQL,你链接的那个文档很棒。谢谢!
    【解决方案3】:

    类似这样的事情,未经测试: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());
    

    【讨论】:

      猜你喜欢
      • 2023-01-28
      • 2016-03-21
      • 2019-09-01
      • 2018-05-20
      • 1970-01-01
      • 1970-01-01
      • 2021-12-30
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多