Php 如何创建“的对象”;“未知”;上课?
我有一个MySQL数据库和一个表tobjects,其中每个记录都有它的Php 如何创建“的对象”;“未知”;上课?,php,oop,Php,Oop,我有一个MySQL数据库和一个表tobjects,其中每个记录都有它的id,参数,值(类似XML),可以说这个参数列决定了对象的“类型” 这些对象在其他一些表中使用,具体取决于它们的类型,因此每个对象都应该以特定的方式处理 因为“处理”有点常见(我使用相同的函数),所以我创建了一个TObject类(不是抽象的,但可以是抽象的),从中继承其他类;这种继承方法非常有用,这也是我使用面向对象编程的原因。例如,TObject具有retrieve()方法,该方法从db获取所有必需的数据,不是TObject
id
,参数
,值
(类似XML),可以说这个参数
列决定了对象的“类型”
这些对象在其他一些表中使用,具体取决于它们的类型,因此每个对象都应该以特定的方式处理
因为“处理”有点常见(我使用相同的函数),所以我创建了一个TObject类(不是抽象的,但可以是抽象的),从中继承其他类;这种继承方法非常有用,这也是我使用面向对象编程的原因。例如,TObject具有retrieve()
方法,该方法从db获取所有必需的数据,不是TObject表中的数据,而是其他依赖于类型的数据,因此我在某些类中重写了它
我遇到的问题是,当我创建一个对象时,我不知道它应该是什么类。当然,我可以从tobjects中选择参数,其中id=$id
,然后(使用开关
)创建适当类的对象,并使用其检索()
方法(每个类检索不同的数据,只有来自tobjects的数据是公共的)从数据库中获取数据,这导致我运行了两次查询,并在类外执行了部分工作,这是可行的,但并不温和
最好的解决方案是,我可以创建一个TObject,然后在检索时,将对象的类更改为我需要的类,它将是TObject的后代,但我几乎肯定这是不可能的
我的解决方案是,我运行第一个查询只是为了从tobjects中选择一个字段,只是为了确定对象的类,对吗?或者在运行时更改对象的类有什么诀窍吗?如果您正确理解所做的事情,下面是我的方法: 将
PDO::FETCH_CLASS | PDO::FETCH_CLASSTYPE
传递给PDOStatement::FETCH()
的第一个参数将返回CLASSPDOStatement::fetchColumn(0)
-换句话说,它根据结果集第一列的值确定要实例化的类名
要利用这一点,您需要在targetTable.objectType=tobjects.id上连接tobjects,并选择tobjects.Parameter
作为结果集中的第一列。如果参数
列已经包含了数据库对象类型到类名的1:1映射,那么您只需要这样做,但是我不确定是否是这样,而且可能不应该是这样,因为这会使以后替换另一个类更加困难
为了克服这个限制,我建议您在第一次连接数据库时创建一个临时表,它将参数
值映射到类名,您可以将其加入到查询中以获得目标类名
因此,流程如下所示:
// 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
}
我会创建一个工厂方法来检查数据(其中应该已经包含参数
)&创建所需类型的对象。工厂方法是您的朋友,尤其是当代码库增长时。然而,从长远来看,检索“所有不同对象之王”的方法可能无法维护……@Wrikken,谢谢您的评论。这似乎是唯一的想法……尽管你认为建立工厂是最明智的做法。@Gordon,是的,我知道,谢谢。工厂是可以的,但我正在通过db记录(第一次查询)循环,然后再次在工厂中循环;我认为可以以某种方式运行一次查询。@Voitcus您使用的是什么DB API?PDO?哇!我还没有测试过,但是这个主意很好。我错过了这个FETCH\u CLASS
和FETCH\u CLASSTYPE
。这正是我需要的。非常感谢。