2011-12-16 200 views
0

想象一下,你有一些对象的列表。这些对象是扩展基类的各种类的实例。 现在我想将这些对象保存在数据库中。动态类实例:良好实践?

作为一个额外的要求,扩展基类的类的数量可能相当大。

它是很好的做法,类名保存为字符串,在数据库中,这样取,

<?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']); 
?> 

是否有任何的做法去做那些以更好的方式什么?

回答

1

除非你编写自己的职能序列化/反序列化使用那些可原生支持PHP一个具体的理由:

你可以阅读更多关于PHP的对象序列化的链接如下:

如果序列化的数据是与外界事物的PHP你可以选择序列化的另一种方法,如JSON或XML共享。但是,如果只是稍后通过PHP存储访问对象的问题,标准的序列化方法已经足够了。


某种标识必须存储与序列化的数据,否则将无法为您确定是什么类型的对象确实是。

当然,我已经看到反序列化方法,其中序列化数据的键已被用于搜索最匹配的对象类型,但这不是我推荐的,因为它不是100%准确的案例。


在您的示例代码片段我认为Page::foo被用作工厂建设新类。

如果您要编写自己的序列化/反序列化数据的方法,并且想要存储对象的所有数据,则不需要强制继承Page的类来实现工厂。

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' 
) 
);