4

私はPropelORMを使用しており、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を使用する前に、次のように見えるPagesクラスの$ nestedという配列に内部ページをネストする関数'loadPages'を持つクラスがありました(注:実際の関数ではなく、厳密な表現です)。

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のWebサイトにあるすべての優れたドキュメントを使用しても、私の努力は大いに役立ちます。

古いPagesクラスでは、$ dataをprint_rすると、次のようになります(上の表を使用した例を1つだけ示します)。

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);

私のスキーマには自己関係の設定がなかったので、このように同じテーブルに外部キーを追加し、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>
4

1 に答える 1

3

これはあなたの質問に対する直接的な回答ではありませんが、それでも解決策です。

質問のコメントで言及したように、nested-setが答えです。

最初はこれが問題を回避する方法のように聞こえるかもしれませんが、ネストされたセットは他の人が同様の問題を抱えている結果です。よく研究されており、木を表現する一般的な方法です。その主な利点は、まさに可変深さのツリーを管理できることです。

あなたは Propel を初めて使用し、ネストされたセットに切り替えるのはかなりの作業になるとおっしゃいました。その場合は、Behaviorsに関するドキュメント セクションを必ずお読みください。

今Propelが好きなら、後で気に入るはずです!

あなたの質問を解決するには: NestedSet Behaviorを見てください。他のすべての動作と同様に、スキーマに簡単に追加できます。モデルを再生成すると、コードに小さなリファクタリングを行うだけで済みます (例でその方法を示します)。

(注: 既存のデータベースがある場合は、その親リンクをネストされたセット構造に移行する必要があります。ただし、基本的にはこれが唯一の懸念事項です。)

ツリー全体を表示する例は、RecursiveIterator の使用セクションにあります。

于 2013-03-25T21:09:02.860 に答える