【问题标题】:How do I best create objects from configuration files?如何最好地从配置文件创建对象?
【发布时间】:2010-07-29 10:35:30
【问题描述】:

我有一组 PHP 类,这些类可以传统上使用构造函数进行实例化。现在我想添加使用 YAML 配置文件实例化这些对象的功能。

以下是描述 Web 表单的配置文件示例:

title: Contact
fields:
    message:
        type: text
        required: true
    topic:
        type: dropdown
        options: ["HTML", "CSS", "PHP"]

这应该会产生一个带有两个对应 Field 对象的 Form 对象。换句话说,配置文件有时会描述包含其他对象的对象。

我不想简单地从 YAML 键/值对映射到 PHP 属性,因为我想在配置文件中允许速记语法。例如,我想缩写一些属性名称,并且还可以输入类似default: today 的内容,其中“今天”不被解释为字符串文字,而是转换为当前时间戳。

由于许多类都是子类,我正在寻找一种解决方案,它还可以让我以某种方式从超类“继承”配置逻辑。

我想避免修改现有的类,但如果它允许更简单的解决方案,我愿意这样做。 再三考虑,我真的不介意修改现有的类;我只对最佳解决方案感兴趣。

如何以这种方式最好地从配置文件创建对象?

【问题讨论】:

    标签: php object configuration-files


    【解决方案1】:

    您可以采取以下方法:

    从配置文件中填充的每个模型类都应该实现一个接口,例如方法fromArray($data)

    在顶层,您知道要创建的对象(表单)的类型。该对象被实例化,并且您的配置文件中的数据传递给 fromArray 方法。然后该对象遍历配置数据并“知道”如何处理每个条目。

    对于“字段”数组的每个元素,它可以将数据传递给子对象 自己可以正确遍历和处理配置(包括以特殊方式对任何接受日期的字段解释“今天”)。

    只需将创建对象的职责分解为知道如何处理此类对象的特殊方法。

    【讨论】:

    • 这实际上是我迄今为止一直在使用的方法,它比我写问题时的预期效果更好。不过,我仍然不确定如何处理继承:假设我有一个扩展 Field 类的 Checkbox 类,我希望 Checkbox 以与 Field 相同的方式读取,除了很少有新的(或不同的)属性。由于超类的fromArray 方法返回该特定类的对象(Field),我不能简单地在子类中调用parent::fromArray。关于如何处理继承的任何想法?
    • 棘手 - 如果 fromArray 不是静态方法,您将不会遇到此问题。在这种情况下,您需要实例化对象(复选框)并使用 fromArray 让它自行配置。
    【解决方案2】:

    我要做的第一件事是看看这个轮子是否已经被某人发明了——这可能涉及查看这里提供的一些 ORM 建议: Good PHP ORM Library?

    编辑:或者在这种情况下查看 YAML Symfony 可能更有用:http://components.symfony-project.org/yaml/ - 这还允许您将 PHP 嵌入到配置文件中,这也应该绕过速记字段名称。

    除此之外,我不会详细介绍您自己实现的细节,因为您可能会选择很多不同的方式来实现它们,并且自己没有实现它们我不想让您误会,但我会建议如果您使用这样的速记语法,您将需要某种方式来标记它是速记语法 - 与 default : %%today%% 或其他更专业的标记相比,default: today 的编码更容易出错。

    【讨论】:

    • ORM 不只是用于将关系数据库中的表映射到 OOP 类吗?
    • 当然,这就是他们开始的地方,但我很确定像 Hibernate 系列这样的更主流的 ORM 库也促进了对象数据的 xml 序列化。不过,你现在让我怀疑自己了。也许我只是老了。
    【解决方案3】:

    我自己写的 PHP 不多,但是如果你在 Symfony 的 YAML 的帮助下自己动手,我可以看到类似的东西。您可以使用PHP Reflection 类获取对象和子对象的所有属性,然后使用Symfony YAML 代码将 YAML 映射到数组,然后将数组映射到属性。在将数组映射到 PHP 对象的属性的代码中,您可以查找您的特殊事物,例如“今天”,并让它们做特殊的事情。

    您可能需要一种标记属性的方法,以便以某种方式对不同的输入做出反应。我不知道它在 PHP 中是否可行,但在 .NET 中,您可以使用 Attribute 类标记属性,让属性知道做一些特殊的事情。

    【讨论】:

      【解决方案4】:

      用 PHP 编写你的配置。

      $ContactConfig=array(
        $title='Contact',
        $fields=array(
          'message'=>array(
            'type'=>'text',
            'required'=>true
          ),
          'topic'=>array(
            'type'=>'dropdown',
            'options'=>array('HTML','CSS','PHP')
          )
        )
      );
      

      【讨论】:

        【解决方案5】:

        编写一个 PHP 代码生成器,它本质上将 YAML 配置转换为 PHP 代码。当您这样做时,操作码缓存(APC、eAccelerator、XCache 等)将使脚本在运行时更高效,而不是 PHP 每次加载时都必须解释 YAML 文件。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2023-03-17
          • 1970-01-01
          • 1970-01-01
          • 2021-07-09
          • 2011-04-22
          • 2015-01-30
          • 1970-01-01
          相关资源
          最近更新 更多