动态类实例:很好的实践



假设您有一个对象列表。这些对象是扩展基类的各种类的实例。现在我想把这些对象保存在数据库中。

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

是否将类名保存为数据库中的字符串并像这样获取它:

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

有没有更好的方法去做类似的事情呢?

除非有特殊的原因需要编写自己的序列化/反序列化函数,否则请使用PHP本地可用的函数:

  • PHP: serialize - Manual
  • PHP: unserialize - Manual

你可以在下面的链接下阅读更多关于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'
  ) 
);

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

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

相关内容

  • 没有找到相关文章

最新更新