我有一个MySQL数据库和一个表格,每个记录都有id
,parameter
,value
(类似XML),可以说这个parameter
列确定对象的“类型”。
对象在其他一些表中使用,具体取决于它们的类型,因此每个表都应以特定的方式处理。
因为“处理”有点普遍(我使用相同的函数)我创建了一个TObject类(不是抽象的但可能是),我继承了其他类;这个继承方法非常有用,这就是我使用面向对象编程的原因。例如,TObject有retrieve()
方法从db获取所有必需的数据,而不是来自tobjects表的那些,但是其他类型依赖于类型,所以我在某些类中覆盖它。
我遇到的问题是,当我创建一个对象时,我不知道它应该是什么类。当然,我可以SELECT Parameter FROM tobjects WHERE id=$id
,然后(使用switch
)创建正确类的对象,并使用其retrieve()
方法(每个类检索不同的数据,只有来自tobjects的数据是常见的)从数据库中获取数据,这导致我运行查询两次,并且在类外部工作的某些部分,这是有效的,但不是很温和。
最好的解决方案是,如果我可以创建一个TObject,然后在检索时,将对象的类更改为我需要的类,它将是TObject的后代,但我几乎可以肯定它是不可能的。
我的解决方案是,我运行第一个查询只是为了从tobjects中选择一个字段来确定对象的类吗?或者是否有在运行时更改对象类的技巧?
答案 0 :(得分: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
}