Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/oop/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Php 如何创建“的对象”;“未知”;上课?_Php_Oop - Fatal编程技术网

Php 如何创建“的对象”;“未知”;上课?

Php 如何创建“的对象”;“未知”;上课?,php,oop,Php,Oop,我有一个MySQL数据库和一个表tobjects,其中每个记录都有它的id,参数,值(类似XML),可以说这个参数列决定了对象的“类型” 这些对象在其他一些表中使用,具体取决于它们的类型,因此每个对象都应该以特定的方式处理 因为“处理”有点常见(我使用相同的函数),所以我创建了一个TObject类(不是抽象的,但可以是抽象的),从中继承其他类;这种继承方法非常有用,这也是我使用面向对象编程的原因。例如,TObject具有retrieve()方法,该方法从db获取所有必需的数据,不是TObject

我有一个MySQL数据库和一个表tobjects,其中每个记录都有它的
id
参数
(类似XML),可以说这个
参数
列决定了对象的“类型”

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

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

我遇到的问题是,当我创建一个对象时,我不知道它应该是什么类。当然,我可以
从tobjects中选择参数,其中id=$id
,然后(使用
开关
)创建适当类的对象,并使用其
检索()
方法(每个类检索不同的数据,只有来自tobjects的数据是公共的)从数据库中获取数据,这导致我运行了两次查询,并在类外执行了部分工作,这是可行的,但并不温和

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


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

如果您正确理解所做的事情,下面是我的方法:

PDO::FETCH_CLASS | PDO::FETCH_CLASSTYPE
传递给
PDOStatement::FETCH()
的第一个参数将返回CLASS
PDOStatement::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
。这正是我需要的。非常感谢。