0

我有一个 MySQL 数据库和一个表 tobjects,其中每条记录都有它的id, parameter, value(类似于 XML),可以说此parameter列确定对象的“类型”。

这些对象在其他一些表中使用,具体取决于它们的类型,因此应以特定方式处理它们中的每一个。

因为“处理”有点常见(我使用相同的函数),所以我创建了一个 TObject 类(不是抽象的,但可能是),我从中继承了其他类;这种继承方法非常有用,这就是我使用面向对象编程的原因。例如,TObject 具有retrieve()从 db 获取所有必要数据的方法,不是 tobjects 表中的数据,而是其他数据,这些数据依赖于类型,因此我在某些类中覆盖它。

我遇到的问题是,当我创建一个对象时,我不知道它应该是什么类。当然,我可以SELECT Parameter FROM tobjects WHERE id=$id,然后(使用switch)创建适当类的对象,并使用它的retrieve()方法(每个类检索不同的数据,只有来自 tobjects 的数据是常见的)从数据库中获取数据,这导致我运行查询二次和课外的一些工作,这很有效,但并不温和。

最好的解决方案是,如果我可以创建一个 TObject,然后在检索时将对象的类更改为我需要的类,它将是 TObject 的后代,但我几乎可以肯定这是不可能的。

我的解决方案是我运行第一个查询只是为了从 tobjects 中选择一个字段来确定对象的类吗?或者是否有在运行时更改对象类的技巧?

4

1 回答 1

1

如果理解你在做什么正确,这里是我会处理这个的方式:

传递PDO::FETCH_CLASS | PDO::FETCH_CLASSTYPE给的第一个参数PDOStatement::fetch()将返回一个类的对象PDOStatement::fetchColumn(0)- 换句话说,它确定要从结果集第一列的值实例化的类名。

为了利用这一点,您可以JOIN tobjects ON targetTable.objectType = tobjects.id选择并选择tobjects.Parameter结果集中的第一列。如果该Parameter列已经包含数据库对象类型到类名的 1:1 映射,这就是您需要做的所有事情,但是我不确定是否是这种情况,而且可能不应该是这种情况,因为它使以后更难替换另一个班级。

为了克服这个限制,我建议您在第一次连接数据库时创建一个临时表,它将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 回答