想象一下,你有一些对象的列表。这些对象是扩展基类的各种类的实例。 现在我想将这些对象保存在数据库中。
作为附加要求,扩展基类的类数量可能非常大。
将类名保存为数据库中的字符串并按以下方式获取是不错的做法:
<?php
class Page {
abstract public function foo($args);
}
class ChartPage : Page{
public function foo($args){
var_dump($args);
}
}
// other classes like ChartPage would be defined here
// fetched row from a MySQL database
$row = array("id" => 21, "title" => "Test", "class" => "ChartPage", "args" => "{}");
$object = new $row['class'];
$object->foo($row['args']);
?>
是否有任何做法以更好的方式做这样的事情?
答案 0 :(得分:1)
除非您有编写自己的序列化/反序列化函数的特定原因,否则请使用PHP中原生的函数:
您可以在以下链接中阅读有关PHP的对象序列化的更多信息:
如果序列化数据要与PHP之外的东西共享,您可以选择其他序列化方法,如JSON或XML。但是,如果只是存储对象以便以后通过PHP访问,标准的序列化方法就足够了。
某些标识符必须与序列化数据一起存储,否则您将无法确定对象的实际类型。
当然,我已经看到了反序列化方法,其中序列化数据的键被用于搜索最匹配的对象类型,但这不是我推荐的,因为它并非100%准确的所有情况。
在您的示例代码段中,我假设Page::foo
将用作构建新课程的工厂。
如果您要编写自己的序列化/反序列化数据的方法,并希望存储对象所有的数据,则不需要强制继承Page
的类来实现工厂。< / p>
Page
也可以通过循环对象包含的键/值对来统一排序任意类的方法。但是这种方法存在一些问题。
如果一个继承的对象有一个相当复杂的成员(即非基本的,例如一个用户定义的类),你可能不想存储它。
例如,如果一个对象具有活动的mysql连接,您只需要存储凭据以重新打开这样的连接,因为您如何将连接本身存储在序列化数据中?
然后,再次存储与套接字连接关联的文件描述符,并使用一个始终在后台运行的虚构MySQLKeepConnAlive
对象保持打开状态很酷,但它通常是必要的。
总之;如果我是你,我会在基础对象中编写一个可用于序列化/反序列化的默认方法,如果继承的类型很复杂,那么开发人员可以覆盖这些方法并提供自己的方法。
我会使用如下所示的数据结构来存储对象,这与您之前描述的不同。 '__PAYLOAD'将包含对象的成员,其他值应在您的基类中定义。
对于两个不同类的实例,'__ PAYLOAD'看起来不一样,但是会有一种统一的方法来加载具有特定id和类型的对象,并找出有关该对象的基本信息。
当然你可以添加比下面更多的“基础”字段,它只是我正在思考的一个例子。
$serialized_data = array (
'__TITLE': 'Test',
'__TYPE': 'CharPage',
'__ID': 21,
'__PAYLOAD': array (
'member_1' => 'foobar',
'member_2' => 'barbaz',
'member_3' => 'bazbir'
)
);
答案 1 :(得分:0)
尝试查看对象序列化。我想这可能会对你有所帮助