オブジェクト|データ|データベース
Mysql から必要な行 (レコード) を取得し、データを読み取り、変更を保存および取得する方法は誰もが知っています。それは明白かつ単純であり、プロセスの背後で煩雑な作業はありません。ただし、オブジェクト指向プログラミング (OOP) を使用してデータベース内のデータを管理する場合、このプロセスを大幅に改善する必要があります。この記事では、データベース レコードを管理するためのオブジェクト指向アプローチを設計する方法について簡単に説明します。データ内のすべての内部論理関係は、非常に組織化されたレコード オブジェクトにカプセル化され、特殊な (特定の) 検証コード システム、変換、およびデータ処理を提供できます。 Zend Engine 2 と PHP 5 のリリースにより、PHP 開発者は作業を支援するためのより強力なオブジェクト指向ツールを利用できるようになり、このプロセス (オブジェクト指向データベース管理) がより魅力的なものになります。
オブジェクトを使用してデータベースを記述する利点の一部を以下に示します:
Accessor メソッドにより、プロパティの読み取りおよび書き込みプロセスを完全に制御できます
Every 最初のレベルの各レコードと属性 (操作) には、確認プロセス
リレーショナルテーブルからのオブジェクトのインテリジェントな取得
論理メソッドの再利用により、すべてのデータ対話が同じ基本コード (コードベース) を経由する必要があるため、メンテナンスが容易になります
異なるレコードの内部ロジックのため、コードがシンプルです煩雑なライブラリ (lib) ファイルの代わりに、それぞれのクラスに既に組み込まれています
コードや SQL クエリ ステートメントを手動で記述する場合、エラーが発生する可能性が低くなります
アクセス メソッド
アクセス方法は、値を割り当てることですクラスを介してインスタンス(インスタンス)の変数。たとえば、User というクラスと $username というインスタンスがあり、User->username() と User->setUsername() を使用してインスタンスの割り当てを返します。
class User {
var $username;
function username() {
return $this->username;
}
function setUsername($newUsername) {
$this->gt; username = $newUsername;
}
}
?>
このような「特別なコード」を記述するには十分な理由があります。このプロセスではクラスを使用する追加の PHP コードが必要ないため、開発者はクラスを変更するという面倒な作業からより高い柔軟性を得ることができます。以下で、より完全な信頼できる User クラスを見てみましょう。
変数 $username は存在しなくなり、すべてが配列 $_data に統合されます
username が空の場合、username() 関数はそれにデフォルト (デフォルト) 値を提供します
setUsername( ) プロセスが確認します値を受け入れる前に、ユーザー名が標準形式 (単語の長さなど) に準拠しているかどうかを確認します
class User {
var $_data = array(); // のすべての属性を含む連想配列User
function username() {
return !empty($this->_data['username']) ? $this->_data['username'] : '(名前なし!)';
}
function setUsername ($newUsername) {
if ($this->validateUsername($newUsername)) {
$this->data['username'] = $newUsername;
}
}
function validateUsername(&$someName ) {
if (strlen($someName) > 12) {
throw new Exception('ユーザー名が長すぎます') // PHP5 のみ
}
return true;
}
}
?>
明らかです。これは、アクセス オブジェクトのデータを制御するのに非常に役立ちます。プログラマがすでにユーザー名情報に直接アクセスしている場合、上記のコード変更によりコードが破損します。ただし、上記のコードでコメントされているように、(クラスの) アクセサー メソッドを使用して、他に何も変更せずに検証機能を追加できます。ユーザー名検証コード (この例では 12 バイトを超えることはできません) は setUsername() メソッドから独立していることに注意してください。検証からデータベースへの保存までのプロセスは簡単です。さらに、これは非常に良い経験則であり、メソッドやクラスが行う必要が少ないほど、再利用される可能性が高くなります。これは、サブクラスの作成を開始するとき、サブクラスが必要で、親クラスのメソッド (動作) の一部の特別な詳細をスキップ (無視) したい場合、(この詳細の) メソッドが小さい場合、さらに明白です。 、(変更する)ことはほんの一時的なプロセスであり、このメソッドが非常に肥大化して複数の目的を果たしている場合は、サブクラスに大量のコードをコピーすることでイライラすることになるかもしれません。
たとえば、Admin が User クラスのサブクラスである場合。 Adamin ユーザー向けに、比較的厳格な異なるパスワード検証方法を使用する場合があります。親クラスの検証メソッドと setUsername() メソッド全体 (子クラスでオーバーライドされる) を検討することをお勧めします。
アクセサーの詳細
アクセサーをより効果的に使用する方法の他の例をいくつか示します。多くの場合、単に静的データを配列で返すのではなく、結果を計算する必要があるかもしれません。アクセサーが実行できるもう 1 つの便利な機能は、キャッシュ内の値を更新することです。すべての変更 (データに対するすべての操作) が setX() メソッドを通過するとき、それは X に基づいてキャッシュ内の値をリセットするときです。
そのため、クラス階層がより明確になります:
内部変数 $_data の処理は、保護されたプライベート メソッド _getData() および _setData() に置き換えられます
そのようなメソッドは、呼び出されるメソッドに移動されます 記録用の抽象スーパークラス (Record)もちろん、これは User クラスのサブクラスです。このレコード クラス (Record クラス) は、配列 $_data へのアクセスの詳細をすべて管理し、内容が変更される前に検証メソッドを呼び出し、変更の通知を Records に送信します。中央の ObjectStore インスタンスと同様です。
class ユーザーは Record {
// --- 省略されたコード --- //
/**
* ユーザーの実際のパスワードは表示されません。パスワード値と同じ strlen を持ついくつかのアスタリスクのみが表示されます。
*/
function password() {
$passLength = strlen($this) を拡張します->_getData('password'));
return str_repeat('*', $passLength);
}
/**
* ユーザーパスワードの設定は影響を受けません。
*/
function setPassword($newPassword) {
$this->_setData( 'password', $newPassword);
}
/**
* fullName は、firstName と lastName から派生した属性です
* ので、変数として保存する必要はありません。
* したがって、読み取り専用であり、「setFullname()」アクセサー メソッドはありません。
*/
function fullName() {
return $this->firstName() " " . }
/**
* 支出制限は、ユーザーの支出制限の通貨値を返します。
* この値はデータベースに INT として保存されるため、より高価な DECIMAL または DOUBLE 列タイプの必要がなくなります
**/
function SpendingLimit() {
return $this->_getData('spendingLimit') / 100;
}
/**
* set アクセサーは通貨値を 100 倍するため、通貨値を再度データベースに保存できます
* INT 値として
*/
function setSpendingLimit($ newSpendLimit) {
$this->_setData('spendingLimit', $newSpendLimit * 100);
}
/**
* validateSpendingLimit はこのクラスでは呼び出されませんが、Record スーパークラスの _setData() メソッドによって自動的に呼び出されます
* その後、setSpendingLimit() メソッドによって呼び出されます。*/
function validateSpendingLimit(&$someLimit) {
if (is_numeric($someLimit) AND $someLimit >= 0) {
return true;
} else {
throw new Exception("支出制限は負でない整数である必要があります"); //PHP5 のみ
}
}
}
/**
* Record はすべてのデータベース オブジェクトのスーパークラスです。
*/
abstract class Record {
var $_data = array();
var $_modifiedKeys = array(); // レコードの作成/取得後に変更されたフィールドを追跡します
/**
* $_data 連想配列から要素を返します。
*/
function _getData($attributeName) {
return $this->_data[$attributeName];
}
/**
* 指定された値が検証に合格した場合、
* $_data 連想配列に値を設定します。
*/
function _setData($attributeName, $value) {
if ( $this->validateAttribute($attributeName, $value)) {
if ($value != $this->_data[$attributeName]) {
$this->data[$attributeName] = $value;
$this->_modifiedKeys[] = $attributeName;
$this->didChange();
} else {
// 新しい値は現在の値と同一です
// 変更は必要ありません
}
}
}
/**
* 「foo」という名前の属性の場合、これは「validateFoo()」という名前のメソッドを探します
* 存在する場合はそれを呼び出します。 それ以外の場合、これは true を返します (検証に合格したことを意味します)。*/
function validateAttribute($attributeName, &$value) {
$methodName = 'validate' . $attributeName;
if (method_exists($this, $methodName)) {
return $this ->$methodName($value);
} else {
return true;
}
}
function DidChange() {
// このレコードが変更されたことを objectStore に通知します
}
}
?>
抽象スーパークラス (Record) ができたので、User クラスに多くのコードを転送し、この User サブクラスをアクセスや検証メソッドなどのユーザーの特別な項目に集中させることができます。 Record クラスに SQL コードがないことに気づいたかもしれません。これは見落としや省略ではありません。 ObjectStore クラス (パート 2 で隠されています) は、データベースとのすべてのやり取りと、スーパークラス Record のインスタンス化を担当します。これにより、Record クラスがより小さく、より効率的になります。これは、大量のオブジェクトをどれだけ効率的に処理できるかを評価する際の重要な要素となります。