3

次のようなクエリを実行すると:

SELECT * FROM user u
LEFT JOIN orders o ON o.user_id=u.id
LEFT JOIN payments p ON p.order_id=o.id

次のようなデータが得られます。

u.id, u.name, o.id, o.item, o.date_time, p.id, p.amount, p.date_time
  99    jeff    17  spring   12-12-2012    12     10.99   13-12-2012
  99    jeff    18     jam   12-12-2012    13       .99   16-12-2012
  99    jeff    19     car   22-12-2012    14      1000   17-12-2012
  99    jeff    19     car   22-12-2012    15      1000   18-12-2012
  99    jeff    19     car   22-12-2012    16      1000   19-12-2012

したがって、ユーザーの Jeff は 3 つの注文を受けており、彼は自分の車に対して 3 回の支払いを行っています。

PHP オブジェクトの User、Order、Payment と単一の DB クエリを指定します。どのようにハイドレートするのでしょうか? 疑似コード、実際のphpコード、または読むべきパターン名を見たい:)

4

2 に答える 2

3

答えがないので、これをどのように解決したかを説明しようと思います。これはおもちゃのソリューションです。

データベースへのクエリは、私が QQL と呼んだ小さな言語で行われます。これは Doctrine 2 DQLに触発されました。

SELECT *
FROM user
JOIN user order
JOIN order payment
WHERE user.name=?

これは解析され、SQL ステートメントを作成できます。解析ツリーは、結果セットをオブジェクト グラフにマップするためにも使用されます。

各モデルには、他のモデルとの「関係」の説明があります。したがって、User には 1 対多の Order があり、Order には 1 対多の Payment があります。説明は、モデル名、主キー、および外部キー名を含む配列にあります。

JOIN を作成するには:

JOIN user order

User モデルを調べて、テーブル名 'users' を取得し、リレーションシップ 'order' を見つけ、Order テーブル名 'orders' と結合キーを取得します。これを使用してビルドします。

JOIN orders o ON o.user_id=users.id

クエリが実行され、結果が返されてオブジェクト グラフが作成されます。私がしたことは、クエリで使用されるすべての個別のモデル (この場合はユーザー、注文、および支払い) を取得し、各行に対してそれぞれをハイドレートすることでした。

// query DB and get results into an array called $rows
foreach ($rows as $row) {
    foreach (array('User', 'Order', 'Payment') as $model) {
        $o = new $model;
        $o->hydrate($row);
        // inspect primary key - have we got this object already? store or throw away
    }
 }

作成されるオブジェクトの多くが重複して削除されるため、私のハイドレート メソッドは非常にシン (迅速) でした。私の質問の結果セットから、User('Jeff') が 5 回ビルドされ、そのうち 4 回が重複して破棄されることがわかります。

結果が読み取られると、オブジェクトの 3 つのリストが表示されます。ユーザー、注文、支払い。これらは、解析ツリーと共にグラフ ビルダーに渡されます。

グラフ ビルダーは、解析ツリーを使用して関係を調べます。「ルート」モデル (「FROM ユーザー」によって決定される) から始めて、解析された QQL を調べて、要求された JOIN (User->id TO Order->user_id) を見つけ、Orders を User->orders 配列に追加します。次に、(Order->id TO Payment->order_id) で同じことを行います。

結果は次のとおりです。

$user->name == 'jeff'
$user->orders[0]->item == 'spring'
$user->orders[1]->item == 'jam'
$user->orders[2]->item == 'car'
$user->orders[2]->payments[2]->date_time == '19-12-2012'

最終的に、ORM、すべてのモデルが拡張する Model_Base (これにより、各モデルに「テーブル名」、「列」、および「関係」があることが保証されます)、QQLParser、およびグラフ ビルダーの 4 つのメイン クラスができました。ORM クラスは 200 行近くあり、群を抜いて最大でした。

結論。できます。Doctrine 2 に似た感じです (そのため、最終的に Doctrine 2 を使用するように移行する際の苦痛は軽減されます)。それはより効率的かもしれません。数千のオブジェクトを読み取ってテスト ページをプロファイリングした結果、最も遅い部分は SQL クエリ (3 ミリ秒) と、モデル クラス (0.7 ミリ秒) を含む mysqli の結果の解放 (1 ミリ秒) でした。書くのは楽しく、たった1日しかかかりませんでした。

于 2012-06-28T15:21:12.007 に答える
0

PDO では、オブジェクトを自動的にハイドレートできます。PDOStatement::fetchObject

于 2012-06-25T15:53:42.757 に答える