zfr/hydrator

Zend Framework 3 hydrator组件原型,提供更好的组件体验

dev-master 2015-09-18 16:06 UTC

This package is auto-updated.

Last update: 2024-08-29 04:12:49 UTC


README

Build Status Scrutinizer Code Quality

该组件是Zend Framework 3 hydrator组件的原型,您可以现在用于新项目(以下为更多详细信息)。与原始实现相比,它提供以下功能:

  • 性能大幅提升(这个新实现比当前实现快5-10倍)
  • 更简洁(在ZF2生命周期的整个过程中,许多被巧妙地集成进来的功能)。
  • 提供内置策略以应对常见用例(目前有DateStrategy以及允许嵌套hydrator的hydrator)。
  • 一些接口已被修改,以提供更明确的表示(例如,查看NamingStrategyInterface)。
  • 通过两个新的上下文对象ExtractionContextHydrationContext,更统一地处理上下文。在ZF2中,您只能在注入阶段获取注入的数组数据,现在您还可以访问注入的对象。
  • 所有内置hydrator都被标记为final

在现有/新项目中使用

此库可在任何项目中使用。如果您是Zend Framework 2用户,您现在实际上可以在新项目中使用它,只需提供以下配置:

use Hydrator\HydratorPluginManager;
use Hydrator\Factory\HydratorPluginManagerFactory;

return [
    'service_manager' => [
        'factories' => [
            HydratorPluginManager::class => HydratorPluginManagerFactory::class
        ]
    ]
];

您可以通过与ZF2 hydrator类似的方式设置hydrator,只需使用“zfr_hydrators”键而不是“hydrators”。

限制

当前实现有一些兼容层,使其与ZF2兼容。例如,此库的hydrator接口扩展了Zend\Stdlib\Hydrator\HydratorInterface。此外,hydrator插件管理器允许您创建Hydrator\HydratorInterface(新)和Zend\Stdlib\Hydrator\HydratorInterface(旧)。

实际上,如果您的第三方模块或其他ZF2组件以非常简单的方式使用hydrator(使用extracthydrate方法),此库可以作为即插即用组件使用,只需进行少量更改。

然而,一旦代码使用更高级的功能,如命名策略、自定义过滤器或策略,有很大可能由于接口冲突而无法使用。因此,在使用此库之前,建议您仔细测试代码。

为什么内置hydrator是final的,我应该怎么使用它们?

这实际上不是ZF3的决定,而是一个实验。我们决定将所有内置hydrator设置为final。这不是一个广为人知的PHP关键字,但基本上,这意味着您不能扩展它们。

这个选择背后的原因是性能。通过确保没有人可以扩展它们,我们可以进行更激进的优化(如缓存)。这导致性能得到显著提升,尤其是对于对象集合。

问题是如何处理过滤属性?如果您之前扩展了ZF2 ClassMethods hydrator,您已经编写了这样的代码

class UserHydrator extends ClassMethods
{
    public function __construct()
    {
        parent::__construct();

        $this->filterComposite->addFilter('password', new MethodMatchFilter('getPassword'), FilterComposite::CONDITION_AND);
    }
}

在此配置下,"getPassword"方法永远不会被hydrator调用,因此此字段永远不会被提取。在这个原型中,您的hydrator实际上组合了一个ClassMethods hydrator。

class UserHydrator implements HydratorInterface
{
    protected $hydrator;

    public function __construct()
    {
        $this->hydrator = new ClassMethods();
    }

    public function extract($object)
    {
        $values = $this->hydrator->extract($object);

        unset($values['password'], $values['anotherValue']);

        return $values;
    }

    public function hydrate(array $data, $object)
    {
        return $this->hydrator->hydrate($data, $object);
    }
}

虽然这更啰嗦,但背后的原因是删除值实际上是业务特定的。您可能只需要为password值清除UserHydrator

此外,这使我们能够执行更多的优化。例如

  • 因为像ArraySerializableHydrator这样的hydrator无法扩展,我们可以肯定过滤功能对这个来说毫无用处,因此它被完全移除(这使得这个hydrator比ZF2的hydrator快得多)。
  • 对于ClassMethods hydrator,我们可以积极缓存很多东西,这样如果您为两个不同的对象运行相同的hydrator,第二次迭代将会快得多。这之所以可能,仅仅是因为final的存在,因为您可能有依赖于上下文的过滤函数,这会使使用如此积极的缓存变得几乎不可能。

当然,由于PHP 5.4 traits,您完全可以轻松地重新创建自己的可继承的ClassMethods hydrator(使用ProvidesNamingStrategyTraitProvidesStrategiesTrait,您可以在几分钟内完成;)。