5

DbTable/Mapper/Model アプローチを使用して、パブリック ライブラリ アプリケーションを大まかにカプセル化するために、Zend Framework で単純な ORM を作成しています。ただし、ユーザー関連のクラスを実行している方法が正しいかどうかはわかりませMapper_UserModel_User

Mapper_User

<?php
class Mapper_Users {

/*
createModelObject would be called by a Controller handling a Form_Regsiter's
data, to create a new Model_User object. This object'd then be saved by the
same Controller by calling Mapper_Users->save();
*/
    public function createModelObject(array $fields) {
        if(!isset($fields['date_registered']))
            $fields['date_registered'] = date('Y-m-d H:i:s');
        if(!isset($fields['max_concurrent_rentals']))
            $fields['max_concurrent_rentals'] = 3;
        return new Model_User($fields);
    }
}
?>

新しいModel_Userオブジェクトを最初から作成する方法 (DB からレコードを取得するのではなく、新しいユーザーを登録する場合など) ではModel_User、フォームから提供された名前/ユーザー名/パスワードを使用して新しいオブジェクトをインスタンス化し、いくつかのオブジェクト プロパティを設定します。登録日、「一度に許可される最大書籍数」など。Model_Userこのデータは、によって内部に詰め込まれ、呼び出されたMapper_Userときに DB に書き込まれます。Mapper_User->save();マッパーは、これを行うのに適した場所のように感じます-モデルを軽く保ちます。

これは正しいですか、それともこのようなデフォルトのフィールドを内部に設定する必要がありますModel_Userか?

モデル_ユーザー

<?php
class Model_User {

    public function setPassword($value) {
        $this->password = md5($value);
    }
}
?>

ユーザー オブジェクトのパスワードを設定するときは、ご想像のとおり、このメソッド内でこれModel_User->setPassword($value);を行っています。繰り返しますが、これは正しいと感じます。メソッド$this->password = md5($value);で md5 ステップを実行しようとすると、パスワード フィールドが明らかに既にハッシュされているため、DB からプルされた場合に問題が発生します。Mapper_User->save();Model_User

そして、これが私の混乱の原因です。私の考えでは、「ユーザーに関係するフィールド」に関連するすべてのロジックは、そのモデルまたはそのマッパーに存在する必要がありますが、ここでは、マッパーにいくつかのロジック (デフォルト フィールド) と、いくつかの (フィールド操作) があります。モデル。これは正しいですか、それともモデルのデフォルト フィールドまたはマッパーのフィールド操作を何らかの方法で取得しようとする必要がありますか?

これを読んでくれてありがとう!


@RockyFordの編集:

Mapper_User 500 個のファイルに同じ基本的なコードを書くのは好きではないので、実際に私が書いた Abstract を拡張しMapper_*.phpます。そのため、多少の官僚主義がありますが、その効果的な__construct() は非常に単純です。

<?php
class Mapper_Users {

    public function __construct() {
        $this->_db = new DbTable_Users();
        if(!$this->_db instanceof Zend_Db_Table_Abstract)
            throw new Exception('Invalid table data gateway provided');
    }
}
?>
4

2 に答える 2

1

完全に答えるには時間がかかるかもしれませんが、setPassword質問から始めましょう。

あなたの現在:

public function setPassword($value) {
        $this->password = md5($value);
    }

これは、慣例やベストプラクティスとは何の関係もありませんが、実用性です。

自問してみてください:

ユーザー オブジェクトのデータベース レコードを取得し、そのデータベース レコードにハッシュ化されたパスワードが含まれているとどうなりますか?

回答:ユーザー オブジェクトと呼び出し$this->setPassword($password);または同等のものを構築するときは、ハッシュをハッシュに適用します。

そのため、マッパーの save() メソッドまたはパスワードの更新に使用されるメソッドでパスワードをハッシュすることがほとんど義務付けられています。データベース テーブルのハッシュ値をパスワードと考え、フォーム フィールドに入力された値をそのパスワードのプレースホルダーと考えてください。

次のパート:

私の考えでは、「ユーザーに関係するフィールド」に関連するすべてのロジックは、そのモデルまたはそのマッパーに存在する必要があります

これはおおむね正しいです。

オブジェクト ドメイン (Model_User) に属するすべてのものはドメイン モデル クラス (Model_User) でアドレス指定されます。

マッパーは、データ オブジェクト (データベース行、json 文字列、xml ファイル、フラット ファイル、csv ファイルなど) を、ドメイン オブジェクト (Model_User) をインスタンス化できる形式に変換 ( map ) するだけです。

そのため、特定のドメイン オブジェクトに対して複数のマッパーが使用可能になったり、1 つのマッパーが複数のデータ ソースにマップされたりする可能性があります。

データを「フィールド」として考えるのをやめて、データベースに頭を悩ませるのをやめ、代わりにオブジェクトをプロパティまたは特性の観点から考えると役立つ場合があります。

最も基本的なレベルに到達すると、Model_Userオブジェクトは次のようになります。

class Model_User {
    protected $id;
    protected $name;
    protected $password;
    //continue....
}

ゲッター、セッター、コンストラクター、およびその他のメソッドはすべてほとんど同じなので、これらの変数に値を入れることができます。

于 2012-09-09T15:25:09.297 に答える
1

DataMapper、オブジェクトにデータを移入し、永続化する役割を果たします。$user->save()ドメインオブジェクト内に永続化ロジックを配置しているため、呼び出すときに物事を混ぜているようです。ActiveRecordこれは、 の代わりにパターンを使用している場合の一般的なアプローチですがDataMappers、これは悪いことです。

オブジェクトDataMapperを保存する責任があり$mapper->save($user);、変更されたプロパティのみを更新する必要があります。そのため、新しいハッシュを設定した場合にのみパスワードが更新されます。

アップデート:

あなたが言った:

Mapper_User->save();[...]メソッドで md5 ステップを実行しようとするとModel_User、パスワード フィールドが明らかに既にハッシュされているため、DB からプルされた場合に問題が発生します。

呼び出されるメソッドを作成setPasswordHash()し、データベースからプルするときにそれを使用します。

覚えておいてください:物を探すな!

マッパー内でデータベースを探すのではなく、データベースを要求する必要があります。

public __construct(Zend_Db_Table $dbTable) {
    $this->dbTable = $dbTable;
}

それはすべて依存性注入に関するものです。

于 2012-09-09T15:28:58.390 に答える