maiorano84/object-hydrator
Composer 安装命令:
composer require maiorano84/object-hydrator
包简介
Hydration package for PHP Objects
关键字:
README 文档
README
A small utility to streamline Object Hydration
Requirements
Object Hydrator requires PHP 8.1 or greater.
Composer
This package may be installed as a Composer dependency by running the following command:
composer require maiorano84/object-hydrator
If you would like to use the latest unstable version, you can run:
composer require maiorano84/object-hydrator:dev-master
Usage
This is a small set of concepts to facilitate the orchestration of object hydration based on varying strategies.
There are 3 concepts that the default Hydration class uses in order to determine how a given input is applied to an object:
- Hydration Keys - These are simple strings that are used to indicate the name of the input that is used. When an input key is matched to a Hydration Key, the value is passed through to the underlying mapping.
- Hydration Mappings - These are objects that store a reference to a given key and a reflection object that points to either a Property or a Method. When a mapping is matched by a given strategy, it will be passed a value that it can use to hydrate the object property.
- Hydration Strategies - These are objects that define the logic used to determine how an input key and value is mapped. Even further, these objects may also determine if a given key and value should be processed recursively by the Hydrator.
Hydration Keys and Hydration Strategies are both set up as Attributes, which may be used to decorate any given class structure marked for Hydration. In this way, you may customize how a given class is Hydrated.
Multiple Hydration Strategies may be applied to a single given class.
Why?
A common task that many REST APIs and ORMs require is the ability to fill arbitary objects with structured data in bulk. The criteria used for setting these values can vary wildly from class to class, and designating a unified interface by which class hydration may occur predictably can prove to be challenging.
The simplest and most common approach would be to have each object implement a given interface that is responsible for the hydration of that entity. The problem with this approach is that it violates the Single-Responsibility principle, and adds extra business logic that the entity itself doesn't really need to be handling.
This removes much of the boilerplate code needed for handling custom hydration rules, while also providing a simple interface by which classes may define their own rules and the order in which they're applied.
Usage
Given a User Entity:
namespace App; class SimpleUser { public string $username; private string $password; public function getPassword(): string { return $this->password; } public function setPassword(string $password): void { $this->password = password_hash($password, PASSWORD_DEFAULT); } }
Hydration of a User entity can be as simple as the following:
use App\SimpleUser; use Maiorano\ObjectHydrator\Hydrator; $hydrator = new Hydrator; $user = $hydrator->hydrate(SimpleUser::class, [ 'username' => 'maiorano84', 'password' => 'secret', ]); print_r($user); /* App\SimpleUser Object ( [username] => maiorano84 [password:App\SimpleUser:private] => <hashedPassword> ) */
By default, classes with no strategy defined will use a combination of the Reflection\PropertiesStrategy and
Reflection\MethodsStrategy in that order. The result will be all keys that match a public property name, and all keys
that match a property setter will be used to hydrate the entity. Note in the above example that the public $username
was hydrated with the value maiorano84, and the private $password was hydrated via the setPassword setter.
More complex structures may also be hydrated like so:
namespace App; use Maiorano\ObjectHydrator\Attributes\HydrationKey; use Maiorano\ObjectHydrator\Attributes\HydrationStrategy; use Maiorano\ObjectHydrator\Strategies\ArrayStrategy; use Maiorano\ObjectHydrator\Strategies\Reflection\MethodsStrategy; use Maiorano\ObjectHydrator\Strategies\Reflection\PropertiesStrategy; #[HydrationStrategy(ArrayStrategy::class, ['_id' => 'id', '_email' => 'email'])] #[HydrationStrategy(PropertiesStrategy::class)] #[HydrationStrategy(MethodsStrategy::class)] class ComplexUser { private int $id; public string $username; private string $email; private string $password; private UserAvatar $avatar; public function getId(): int { return $this->id; } public function getEmail(): string { return $this->email; } public function getUserPassword(): string { return $this->password; } #[HydrationKey('_password')] public function setUserPassword(string $password): void { $this->password = password_hash($password, PASSWORD_DEFAULT); } public function getAvatar(): UserAvatar { return $this->avatar; } public function setAvatar(UserAvatar $avatar): void { $this->avatar = $avatar; } } #[HydrationStrategy(PropertiesStrategy::class, ReflectionProperty::IS_PUBLIC | ReflectionProperty::IS_PRIVATE)] class UserAvatar { #[HydrationKey('_id')] private int $id; public string $name; private string $filePath; public function getUrl(): string { return sprintf('https://mydomain.com/images/%s/%d-%s', $this->filePath, $this->id, $this->name); } }
There are a number of things going on here:
- An
ArrayStrategymay be used to explicitly map certain input keys to properties or methods. - We are chaining
PropertiesStrategyandMethodsStrategyfallbacks to default to the appropriate public properties/setters behaviors for keys that aren't defined in theArrayStrategy - The
UserAvatarclass is allowing both private and public properties to be set for its implementation of thePropertiesStrategy HydrationKeyis used to override the input keys in certain areas that would otherwise be difficult to determine through reflection
Hydration can be done similarly as before:
use App\ComplexUser; use Maiorano\ObjectHydrator\Hydrator; $hydrator = new Hydrator; $user = $this->hydrator->hydrate(ComplexUser::class, [ '_id' => 1, '_email' => 'maiorano84@gmail.com', '_password' => 'secret', 'username' => 'maiorano84', 'avatar' => [ '_id' => 123, 'name' => 'maiorano84.jpg', 'filePath' => 'path/to/avatars' ], ]); print_r($user); /* App\ComplexUser Object ( [username] => maiorano84 [id:App\ComplexUser:private] => 1 [email:App\ComplexUser:private] => maiorano84@gmail.com [password:App\ComplexUser:private] => <hashedPassword> [avatar:App\ComplexUser:private] => App\UserAvatar Object ( [name] => maiorano84.jpg [id:App\UserAvatar:private] => 123 [filePath:App\UserAvatar:private] => path/to/avatars ) ) */
The Hydrator
The Hydrator can be thought of as an orchestration tool. It doesn't really do any property setting or method invocations itself, but rather loops through all of the key/value pairs and determines the best Strategy to use.
Hydration Strategies
Hydration Strategies encapsulate the logic to determine how input keys and values are mapped to properties or methods. Every Hydration Strategy will expose an underlying Mapping Interface that can be used to define the relationship between a given key and its associated property/method.
Other methods are used to determine if a given key is available within a strategy, or if a value can be considered recursive.
See the Maiorano\ObjectHydrator\Strategies\HydrationStrategyInterface for more details.
Hydration Mappings
Mappings carry both a Hydration Key as well as a Reflection Object containing information about the associated property or method. A mapping serves primarily to store a given association, as well as to complete the appropriate hydration invocation.
See the Maiorano\ObjectHydrator\Mappings\HydrationMappingInterface for more details.
Hydration Keys
Hydration Keys serve as indicators for input. All input for a given hydration attempt is expected to be a structured associative array, with all keys of the array representing an expected Hydration Key.
The default Reflection Strategies will look first to any Properties/Methods with an explicit HydrationKey decorator.
If no Attributes are found, then the Reflection Strategies will try to determine one by name:
- In the case of Properties, matching names will be considered an association and a Mapping will be created.
- In the case of Methods, if the method starts with
setand the rest of its name matches a given property, then a Mapping will be created using that key. - The Reflection Strategies default only to
publicproperties or methods. This may be overriden using theHydrationStrategydecorator.
Other Notes
Possible points of improvement:
- Method Reflection is currently limited only to one parameter for recursion.
- Additional attributes may be needed to flesh out possible exclusion logic to prevent mapping on public properties
maiorano84/object-hydrator 适用场景与选型建议
maiorano84/object-hydrator 是一款 基于 PHP 开发的 Composer 扩展包,目前已累计 4 次下载、GitHub Stars 达 0, 最近一次更新时间为 2022 年 03 月 28 日, 在 PHP 生态内属于活跃度较高的组件。
它主要适用于以下技术方向: 「entities」 「hydration」 等业务场景。在实际项目中,围绕这些方向常见需要落地的问题包括:接口对接、性能调优、并发安全、与既有框架(Laravel / ThinkPHP / Yii / Webman 等)的兼容适配,以及生产环境的日志埋点与稳定性保障。
我们在过去多个企业项目中使用过 maiorano84/object-hydrator 或与其功能相近的方案,如果你在选型或落地过程中遇到问题,例如 版本兼容、二次改造、私有化封装、与内部系统对接、生产 BUG 排查,欢迎联系我们协助评估。
基于 maiorano84/object-hydrator 在你已有业务上做功能扩展、字段裁剪、UI 适配、与内部账号 / 权限 / 日志系统的深度对接。
线上偶发问题、内存泄漏、慢查询、并发异常等排查修复;针对高流量场景做缓存、队列、索引层面的调优。
承接完整的项目从需求 → 设计 → 开发 → 上线 → 长期运维;也可按月提供技术保姆服务。
与 maiorano84/object-hydrator 相关的其它包
同方向 / 同关键字的高下载量 PHP Composer 包推荐,方便对比选型:
Library for merging source data to destination data only if destination data remains valid after that
Integrates data-mapper in Symfony projects.
A simple library that uses the hydration pattern to fill objects given different sources of data.
Communibase entities
Behaviors for hydration and extraction of embedded models for yii2 framework
Simple, safe and flexible implementation of handling SQL entities and repositories as well as multi-table SQL queries while staying lightweight and straightforward.
统计信息
- 总下载量: 4
- 月度下载量: 0
- 日度下载量: 0
- 收藏数: 0
- 点击次数: 3
- 依赖项目数: 0
- 推荐数: 0
其他信息
- 授权协议: MIT
- 更新时间: 2022-03-28