8

というテーブルとCatという PHP クラスがありCatます。CatDataMapper今、私はクラスを作りたいので、 Cat extends CatDataMapper.

Data Mapper クラスで、ORM を実行したり、Cat を作成、編集、削除したりするための基本的な機能を提供したいと考えています。

そのために、このパターンをよく知っている誰かが私に役立つアドバイスをくれるでしょうか?update()、delete()、save() などの関数を提供するだけでは少し単純すぎると思います。

Data Mapper にはこの問題があることに気付きました: まず、Cat のインスタンスを作成し、次に name、furColor、eyeColor、purrSound、meowSound、attendants などのすべての変数を初期化します。すべての設定が完了したら、save( ) CatDataMapper から継承された関数。これは単純なことでした ;) しかしここで、本当の問題: データベースに猫のクエリを実行すると、多くの猫のデータを含む単純で退屈な結果セットが返されます。

PDO には、Cat インスタンスを作成するための ORM 機能があります。私がそれを使用しているとしましょう。あるいは、連想配列を取る mapDataset() 関数があるとさえ言えます。しかし、データ セットから Cat オブジェクトを取得するとすぐに、冗長なデータができてしまいます。同時に、20 人のユーザーがデータベースから同じ猫のデータを取得し、猫のオブジェクトを編集することができます。つまり、猫の名前を変更して、それを保存します。彼ら全員が編集を保存すると、すべてが台無しになります。

うーん... わかりました、この質問を非常に短くするために、ここでの良い習慣は何ですか?

4

5 に答える 5

12

PoEA の DataMapperから

Data Mapper は、インメモリ オブジェクトをデータベースから分離するソフトウェアのレイヤーです。その役割は、2 つの間でデータを転送し、それらを互いに分離することです。Data Mapper を使用すると、メモリ内オブジェクトはデータベースが存在することさえ知る必要がありません。SQL インターフェースのコードは必要なく、データベース スキーマの知識もまったく必要ありません。(データベース スキーマは、それを使用するオブジェクトを常に認識しません。) これは Mapper (473) の形式であるため、Data Mapper 自体はドメイン レイヤーには認識されません。

したがって、Cat は CatDataMapper を拡張しないでください。is-a 関係が作成され、Cat が Persistence レイヤーに結び付けられるためです。この方法で Cat からの永続性を処理できるようにしたい場合は、ActiveRecordまたはその他のデータ ソース アーキテクチャ パターンを調べてください。

通常、ドメイン モデルを使用する場合は DataMapper を使用します。単純な DataMapper は、フィールドごとにデータベース テーブルを同等のメモリ内クラスにマップするだけです。ただし、DataMapper が必要になった場合、通常、このような単純な関係はありません。テーブルはオブジェクトに 1:1 でマップされません。代わりに、複数のテーブルを 1 つのオブジェクト集合体にすることができ、その逆も可能です。そのため、 CRUD メソッドだけを実装するのは非常に困難です。

それとは別に、これはより複雑なパターン (PoEA では 15 ページをカバー) の 1 つであり、特にリポジトリ パターンと組み合わせて使用​​されることがよくあります。同様の質問については、このページの右側にある関連する質問の列を参照してください。

複数のユーザーが同じ Cat を編集しているという質問については、これはConcurrencyと呼ばれる一般的な問題です。その解決策の 1 つは、誰かが編集している間、行をロックすることです。しかし、すべての場合と同様に、これは他の問題につながる可能性があります。

于 2009-12-28T18:16:02.670 に答える
2

DoctrinePropelなどの ORM に依存している場合、基本的な原則は、データベースから実際のデータを取得する静的クラスを作成することです (たとえば、Propel は CatPeer を作成します)。Peer クラスによって取得される結果は、"水和」を猫オブジェクトに変換します。

ハイドレーション プロセスは、「単純で退屈な」MySQL の結果セットを、ゲッターとセッターを持つ優れたオブジェクトに変換するプロセスです。

したがって、取得には次のようなものを使用しますCatPeer::doSelect()。次に、新しいオブジェクトの場合、最初にインスタンス化します (または、DB から取得してインスタンス化します)。 $cat = new Cat();

挿入は、実行するのと同じくらい簡単です:$cat->save();これは、挿入 (または、オブジェクトがデータベースに既に存在する場合は更新) と同等です... ORM は、for を使用して、新しいオブジェクトと既存のオブジェクトの違いを行う方法を知っている必要があります。たとえば、主キーの有無)。

于 2009-12-28T18:11:54.817 に答える
2

PHP 5.3 未満では、データ マッパーの実装は非常に困難です。保護されたフィールドやプライベート フィールドを読み書きできないためです。オブジェクトをロードおよび保存する際には、いくつかの選択肢があります。

  1. オブジェクトをシリアル化し、文字列表現を変更し、unserialize で元に戻すなど、何らかの回避策を使用してください。
  2. すべてのフィールドを公開する
  3. それらを非公開/保護し、それぞれにミューテーター/アクセサーを記述します

最初の方法は、新しいリリースで壊れる可能性があり、非常に粗雑なハックです。2 番目の方法は、(非常に) 悪い習慣と見なされます。

3 番目のオプションも悪い習慣と見なされます。すべてのフィールドに getter/setter を提供するのではなく、必要なフィールドだけに提供する必要があるためです。永続化メカニズムのためにのみ必要なメソッドがモデルに含まれているため、純粋な DDD (ドメイン駆動設計) の観点から見ると、モデルは「破損」します。また、フィールド -> セッター メソッド、フィールド -> テーブル列の隣に別のマッピングを記述する必要があることも意味します。

PHP 5.3 では、リフレクションを使用して、すべてのタイプのフィールドにアクセス/変更する機能が導入されています。

http://hu2.php.net/manual/en/reflectionproperty.setaccessible.php

これにより、すべてのフィールドにミューテーターを提供する必要がなくなるため、真のデータ マッパーを実現できます。

于 2009-12-29T01:51:25.203 に答える
1

PDO には、Cat インスタンスを作成するための ORM 機能があります。私がそれを使用しているとしましょう。あるいは、連想配列を取る mapDataset() 関数があるとさえ言えます。しかし、データ セットから Cat オブジェクトを取得するとすぐに、冗長なデータができてしまいます。同時に、20 人のユーザーがデータベースから同じ猫のデータを取得し、猫のオブジェクトを編集することができます。つまり、猫の名前を変更して、それを保存します。彼ら全員が編集を保存すると、すべてが台無しになります。

通常、データの状態を追跡するために、IdentityMap および/または UnitOfWork が使用され、マップされたエンティティに対するすべての異なる操作を追跡し、要求サイクルの最後に操作が実行されます。

于 2009-12-28T18:19:20.480 に答える
0

答えを短くしてください。Cat のインスタンスがあります。(おそらく、CatDbMapper または Cat3rdpartycatstoreMapper を拡張します) 次のように呼び出します。

$cats = $cat_model->getBlueEyedCats();
//then you get an array of Cat objects, in the $cats array

何を使用するかわからない場合は、いくつかの php フレームワークを調べて理解を深めてください。

于 2009-12-28T17:52:34.347 に答える