动态类实例:良好实践?

时间:2011-12-16 20:06:37

标签: php class reflection

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

作为附加要求,扩展基类的类数量可能非常大。

将类名保存为数据库中的字符串并按以下方式获取是不错的做法:

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

是否有任何做法以更好的方式做这样的事情?

2 个答案:

答案 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)

尝试查看对象序列化。我想这可能会对你有所帮助

http://php.net/manual/en/language.oop5.serialization.php