今日からモデルを紹介します。モデルはフレームワークの非常に重要な部分であり、実際にはこのすべての処理をモデル内で行うことができません。
Java の場合、フレームワークがなくても、そのモデルは非常に複雑です。まずサービス インターフェイスを作成し、次に実装を作成し、次に DAO インターフェイスを定義し、DAO 実装を定義して、これらのレイヤーを定義します。これはドメイン間でデータを転送するための POJO であると考えてください。
Java の契約型プログラミング手法は非常に優れており、後続の実装クラスが変更されてもインターフェイスは変更されず、コードの修正量もそれほど多くありません。
PHPではこれをあまり深く抽象化しすぎると、どうしても抽象化が浅くなり、その後のモデル層のメンテナンスが難しくなるという問題があります。
まず、DB にアクセスする最も一般的な方法について説明します。1 つのテーブルだけに注目すると、テーブル モデルが存在します。これを DbTable と呼びます。テーブル間の関係について テーブル間に関連がある場合、DbRelation と呼ばれるリレーショナル モデルが存在します。
DbTable は 1 つのテーブルにのみ関連付けられているため、その操作は比較的単純ですが、DbRelation はテーブル間の関係を扱うため、より複雑です。
次に、システムに管理者、一般ユーザー、訪問者の 3 つの役割がある場合、これら 3 つの役割の基本情報は同じであるため、DB には対応する 2 つのテーブルがあります。
1. ユーザーの基本情報を格納するユーザー テーブルには、次のフィールドがあるとします: 。
uid userName パスワード蓋
注: 蓋は論理的には、後で説明する Limits テーブルの外部キーです。
2. Limits テーブルにはユーザー権限情報が保存され、次のフィールドがあります:
蓋の制限
Limits は int 型の値です。1 は一般ユーザーを表し、2 は管理者を表すとします。訪問者は User テーブルに記録されないため、このテーブルには記録されません。
対応するモデルは次のとおりです:
ユーザーと制限の 2 つのテーブル モデルがあります。
次に、User モデルを例に挙げます。このクラスの基本情報は次のとおりです。
1 |
2 | class User { |
3 | private $_pk = 'uid'; |
4 | private $_tableInfo = array( |
5 | 'uid','userName','password','lid' |
6 | ); |
7 | private $_tablePrefix = ''; |
8 | private $_tableName = ''; |
9 | } |
$_pk 変数を使用してこのテーブルの主キーを表し、テーブル情報を $_tableInfo に保存します。$_tablePrefix はテーブルのプレフィックスを表し、複数のアプリケーション テーブルが同じ名前 $ を持つことを防ぎます。 _tableName (論理的に) テーブルの物理名は $_tablePrefix です。 もちろん、$_tableSuffix を定義することもできます。
リレーショナル モデルの場合、User テーブルと Limits テーブルの間の関係は次のように記述できます:
<テーブル>
01 |
02 | class Lid { |
04 | 'User','Limits' |
05 | ); |
06 | private $_tablesInfo = array( |
07 | 'Users' => array( |
08 | 'uid','userName','password','lid' |
09 | ), |
10 | 'Limits' => array( |
11 | 'lid','limits' |
12 | ) |
13 | ); |
14 | private $_mainTable = 'User'; |
15 | } |
ここでの $_tables は 2 つのテーブル間の関係を指定し、$_tablesInfo はテーブルの基本情報も指定し、$_mainTable はどのテーブルがメイン テーブルであるかを指定します。
モデル層がこのように抽象化されている場合、テーブル モデルまたはリレーショナル モデルがコントローラー内で直接インスタンス化されると仮定してみましょう。
ログインを完了するためのログイン メソッドが User モデルにあり、戻り値が bool であるとします。このメソッドの特定の実装は気にしないため、コントローラー内のコードは次のようになります。 :
01 |
02 | class IndexController extends Controller { |
04 | $userName = empty($_GET['userName']) ? null : trim($_GET['userName']); |
02
05 | $password = empty($_GET['password']) ? null : trim($_GET['password']); |
06 | if((null === $userName) (null === $password)) { |
07 | //跳转 |
08 | } else { |
09 | $user = new User(); |
10 | if($user->login($userName,$password)) { |
11 | //Success,然后设置session或cookie,跳转 |
12 | } else { |
13 | //Fail,跳转 |
14 | } |
15 | } |
16 | } |
17 | } |
これを行うことに問題はありますか?
1. テーブル モデルの場合、ログインという言葉はビジネスと密接に関係しているため、ビジネスから完全に分離することが最善です。いくつかの基本的な操作;
2. 現在 DB に直接アクセスしていない場合は、まず memcache にこのキーがあるかどうかを確認し、ある場合は memcache から直接アクセスし、ない場合は DB にアクセスして、値を memcache に設定します。この場合、最初にコントローラーで書かれていないコードを大量に書き込むしか方法はありません。
そこで、ここでは、コントローラー、テーブル モデル、リレーショナル モデルの間にある別のレイヤーを抽象化します。このように、コントローラーはビジネスに密接に関係するこのレイヤーにアクセスできます。テーブル モデルとリレーショナル モデルを複雑なビジネスから分離することで、将来のプロジェクトの拡張に非常に役立ちます。先ほどの例を引き続き使用します。このクラスの名前が UserModel であると仮定すると、そのコードは次のようになります。
01
01 |
02 | class UserModel { |
03 | public function login($userName,$password) { |
04 | $user = new User(); |
05 | if($user->isPasswordCorrect($userName,$password)) { |
06 | //设置cookie或session,不写了 |
07 | return true; |
08 | } else { |
09 | //密码不正确 |
10 | return false; |
11 | } |
12 | } |
13 | } |
したがって、コントローラーのコードは次のようになります:
01 |
02 | class IndexController extends Controller { |
04 | $userName = empty($_GET['userName']) ? null : trim($_GET['userName']); |
02
05 | $password = empty($_GET['password']) ? null : trim($_GET['password']); |
06 | if((null === $userName) (null === $password)) { |
07 | //跳转 |
08 | } else { |
09 | $userModel = new UserModel(); |
10 | if($userModel->login($userName,$password)) { |
11 | //Success,跳转 |
12 | } else { |
13 | //Fail,跳转 |
14 | } |
15 | } |
16 | } |
17 | } |
コントローラーにはビジネス ロジック処理コードはなく、User クラスの名前は isPasswordCorrect という非常に意味のあるものになっています。
コントローラー、テーブル モデル、リレーショナル モデルの間の層をモデルと呼びます (Java のサービス層に非常に似ています)。このように、コントローラーを作成するプログラマは、コードを見るだけで済みます。モデル層では、モデル層がリレーショナル モデルを呼び出すかテーブル モデルを呼び出すかは関係ありません。
実際、モデルは完全に DB の操作であると考えられますが、このモデルではキャッシュを抽象化できます。さあ、キャッシュインターフェイス ICache を書きます:
1 |
2 | interface ICache { |
3 | public function connect(); |
4 | public function get($name); |
5 | public function set($name,$val,$expire = null); |
6 | public function have($name); |
7 | public function remove($name); |
8 | public function clear(); |
9 | } |
次に、別のキャッシュに対して、このインターフェイスを実装するだけです。
先ほど検討したのは Cache です。実際には、nosql もいくつかあります。もちろん、ここでは書きません。