0

MySQL データベースとテーブル tobjects があり、各レコードにはid, parameter, (XML のようなもの) があり、この列がオブジェクトの「タイプ」を決定するvalueと言えます。parameter

オブジェクトは、そのタイプに応じて他のいくつかのテーブルで使用されるため、それぞれを特定の方法で処理する必要があります。

「処理」はやや一般的であるため (私は同じ関数を使用します)、他のクラスを継承する TObject クラス (抽象的ではありませんが、抽象的である可能性があります) を作成しました。この継承方法は非常に便利で、それこそが私がオブジェクト指向プログラミングを使用する理由です。たとえば、TObject にはretrieve()、必要なすべてのデータを db から取得するメソッドがあり、tobjects テーブル内のものではなく、タイプに依存する他のデータも取得するため、いくつかのクラスでそれをオーバーライドします。

私が遭遇した問題は、オブジェクトを作成するときに、それがどのクラスであるべきかわからないことです。もちろん、SELECT Parameter FROM tobjects WHERE id=$id( を使用してswitch) 適切なクラスのオブジェクトを作成し、そのretrieve()メソッドを使用して (各クラスは異なるデータを取得し、tobjects からのデータのみが共通です)、db からデータを取得します。これにより、クエリ 2 を実行します。時間とクラス外の作業の一部は機能しますが、穏やかではありません。

最善の解決策は、TObject を作成し、取得時にオブジェクトのクラスを必要なクラスに変更することです。これは TObject の子孫になりますが、それが不可能であることはほぼ確実です。

オブジェクトのクラスを決定するためだけに tobjects から 1 つのフィールドを選択するためだけに最初のクエリを実行するという私の解決策はありますか? または、実行時にオブジェクトのクラスを変更するトリックはありますか?

4

1 に答える 1

1

あなたが正しくやっていることを理解していれば、これが私がこれにアプローチする方法です:

PDO::FETCH_CLASS | PDO::FETCH_CLASSTYPEの最初の引数に渡すと、PDOStatement::fetch()クラスのオブジェクトが返さPDOStatement::fetchColumn(0)れます。つまり、結果セットの最初の列の値からインスタンス化するクラス名が決定されます。

これを活用するには、結果セットの最初の列としてJOIN tobjects ON targetTable.objectType = tobjects.id選択します。tobjects.Parameter列がデータベース オブジェクト型とクラス名の 1:1 マッピングを既に保持している場合Parameterは、これで十分ですが、これが当てはまるかどうかはわかりません。後日、別のクラスを代用することはより困難です。

この制限を克服するには、最初にデータベースに接続するときに一時テーブルを作成することをお勧めします。これにより、Parameter値がクラス名にマップされます。これJOINにより、クエリで対象のクラス名を取得できます。

したがって、フローは次のようになります。

// Set up the connection
$db = new PDO('mysql:yourDSNhere');
$db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$db->setAttribute(PDO::ATTR_EMULATE_PREPARES, false);

// Create a temp table to store the mapping
$db->query("
  CREATE TEMPORARY TABLE `objectMappings` (
    `Parameter` INT NOT NULL PRIMARY KEY,
    `ClassName` VARCHAR(255)
  ) ENGINE=MEMORY
");

// A mapping of Parameter IDs to class names
$classMap = array(
  1 => 'Class1',
  2 => 'Class2',
  3 => 'Class3',
  // ...
);

// Build a query string and insert
$rows = array();
foreach ($classMap as $paramId => $className) {
  // this data is hard-coded so it shouldn't need further sanitization
  $rows[] = "($paramId, '$className')";
}

$db->query("
  INSERT INTO `objectMappings`
    (`Parameter`, `ClassName`)
  VALUES
    ".implode(',
    ', $rows)."
");

// ...

// When you want to retrieve some data
$result = $db->query("
  SELECT m.ClassName, t.*
  FROM targetTable t
  JOIN tobjects o ON t.objectType = o.id
  JOIN objectMappings m ON o.Parameter = m.Parameter
  WHERE t.someCol = 'some value'
");

while ($obj = $result->fetch(PDO::FETCH_CLASS | PDO::FETCH_CLASSTYPE)) {
  // $obj now has the correct type, do stuff with it here
}
于 2013-03-06T10:46:21.793 に答える