php - 插入 ORM 自引用外键

标签 php mysql orm propel

我正在使用 Propel ORM 并且对 Propel 很陌生。我需要一些帮助从表中选择数据,但我无法正确查询。我有一个这样的表(注意:不是实际的表,而是相同的主体):

+---------------------+
| ID  | Page | Parent |
+---------------------+
| 1   |  A   |  0     |
| 2   |  B   |  0     |
| 3   |  C   |  2     |
| 4   |  D   |  3     |
| 5   |  E   |  1     |
| 6   |  F   |  0     |
| 7   |  G   |  3     |
| 8   |  H   |  4     |
| 9   |  I   |  6     |
| 10  |  J   |  5     |
+---------------------+

加载页面时,此表为我提供了树状结构。在使用 propel 之前,我有一个带有函数“loadPages”的类,它将内页嵌套在 Pages 类中名为 $nested 的数组中,看起来像这样(注意:不是实际函数,只是一个近似表示):

function loadPages($parent=0, $data){
    $sql = "sql query here to select pages where parent = $parent";
    while($results){
       $pages = new Pages();
       $pages->setId(blah blah);
       $pages->setPage(blah blah);
       $pages->setParent(blah blah);

       $innerPages = new Pages();
       /* load innerpages into the nested array */
       $innerPages->loadPages($pages->getId(), $pages->nested);

       array_push($data, $pages);
       return true;
    }
}

基本上我如何使用 Propel 做到这一点?我可以像这样轻松地提取父值为 0 的页面:

$pages = PagesQuery::create()
->filterByParent(0)
->find();

但我需要递归地将内页嵌套到它返回的对象中,即使 Propel 网站上有所有好的文档,我的努力也没有取得多大成果。

使用我的旧 Pages 类,如果我 print_r $data 我会得到这样的东西(这里只是一个使用上表的例子。):

Array(
   [0] => Pages Object
   (
    [id] => 2
    [page] => B
    [parent] => 0
    [nested] = Array(
       [0] => Pages Object
       (
        [id] => 3
        [page] => C
        [parent] => 2
       )
    )
)

我已经让这个工作了,但我不确定这是最好的方法。

function loadPages($parent=0, $siteId, &$arr){
        $arr = PagesQuery::create()
        ->filterBySiteId($siteId)
        ->filterByParentId($parent)
        ->find();

        foreach ($arr as $i => $v) {
            $arr[$i]->nested = '';
            loadPages($v->getId(), $siteId, $arr[$i]->nested);
        }

    }
    $site->pages = '';
    loadPages(0, $site->getId(), $site->pages);

我的模式没有 self 关系设置,所以我像这样向同一个表添加了一个外键,然后重新运行 propel 以重新创建类。我仍然不确定如何写出推进查询(我已经从模式中删除了几列只是为了节省空间)。抱歉,帖子现在变得很糟糕。

<table name="pages" phpName="Pages">
    <column name="id" type="integer" required="true" primaryKey="true" autoIncrement="true"/>
    <column name="userId" type="integer" required="false"/>
    <column name="siteId" type="integer" required="false"/>
    <column name="parentId" type="integer" required="false"/>
    <foreign-key foreignTable="users" phpName="Users" refPhpName="Pages">
         <reference local="userId" foreign="id"/>
        </foreign-key>
    <foreign-key foreignTable="sites">
          <reference local="siteId" foreign="id"/>
        </foreign-key>
        <foreign-key foreignTable="pages">
         <reference local="parentId" foreign="id"/>
        </foreign-key>
</table>

最佳答案

这不是您问题的直接答案,但它仍然是一个解决方案。

正如您在对问题的评论中提到的:nested-set 就是答案。

起初这听起来像是解决问题的方法,但 nested-set 是其他人遇到类似问题的结果。它经过深入研究,是一种流行的表示树木的方式。它的主要优势恰恰是能够管理可变深度树。

您提到您是 Propel 的新手,切换到嵌套集需要大量工作,所以我冒昧地假设您以前没有使用过 Propel 的行为。如果是这种情况,请务必阅读有关 Behaviors 的文档部分。 .

如果您现在喜欢 Propel,以后您会喜欢它!

要解决您的问题:请查看 NestedSet Behavior .与所有其他行为一样,很容易将其添加到您的架构中。重新生成您的模型,您只需对代码进行少量重构(示例将向您展示如何重构)。

(注意:如果您有现有数据库,则需要将该父链接迁移到嵌套集合结构。但这基本上是您应该关心的唯一问题。)

Using a RecursiveIterator 中提供了显示整棵树的示例部分。

关于php - 插入 ORM 自引用外键,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15567976/

相关文章:

php - 流膨胀包装器?

php - Wordpress:计算标签使用的总次数

mySQL 更新接下来的 12 个 NULL 值,日期递增 1

mysql - 我如何判断 'state' 的最后 x 行是否 = 1

nhibernate - 说服顽固的DBA将ORM用于大多数CRUD与存储过程, View 和函数

java - 如何在 hibernate 映射中添加另一个搜索参数?

php - MySQL 在严格模式下运行并给我带来了问题。如何解决这个问题?

php - CakePHP:在两个查询中完成的连接、belongsTo 和 hasMany 关系很少

mysql - 选择多个表并生成一个新表

python - 任何 Python OLAP/MDX ORM 引擎?