答えがないので、これをどのように解決したかを説明しようと思います。これはおもちゃのソリューションです。
データベースへのクエリは、私が 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日しかかかりませんでした。