nandan108/prop-access
最新稳定版本:v0.5.0
Composer 安装命令:
composer require nandan108/prop-access
包简介
Accessor layer for PHP objects using reflection, extensible via custom resolvers
README 文档
README
A minimal and extensible property accessor library for PHP objects.
Provides getter and setter resolution via reflection, supporting both public properties and get*/set* methods.
Designed to be:
- ✅ Framework-agnostic
- 🔌 Easily extensible to support more object types
🛠 Installation
composer require nandan108/prop-access
🔧 Features
- 🧠 Default resolvers for public properties and
getProp()/setProp()methods - 🧩 Pluggable resolver priority (later-registered resolvers are called first)
- 🧼
CaseConverterutility for camelCase, snake_case, kebab-case, etc. - 🧰 Convenience methods:
getValueMap(),resolveValues(),canGetGetterMap()...
🚀 Usage
Accessor maps are cached by class name, so the returned closures are stateless and require the target object to be passed as an argument:
use Nandan108\PropAccess\PropAccess; $getterMap = PropAccess::getGetterMap($myObj); $value = $getterMap['propertyName']($myObj); $setterMap = PropAccess::getSetterMap($myObj); $setterMap['propertyName']($myObj, $newValue);
To resolve only specific properties:
$getters = PropAccess::getGetterMap($myObj, ['foo_bar']);
🧰 Convenience Utilities
Quickly resolve values from a target object:
use Nandan108\PropAccess\PropAccess; $values = PropAccess::getValueMap($myDto); // → ['prop1' => 'value1', 'prop2' => 42, ...]
You can also resolve values from a previously obtained getter map:
$getters = PropAccess::getGetterMap($entity, ['foo', 'bar']); $values = PropAccess::resolveValues($getters, $entity);
Check if accessors are supported for a given target:
if (PropAccess::canGetGetterMap($target)) { // Safe to call getGetterMap() }
These methods are especially useful when working with dynamic sources, fallbacks, or introspection-based tools.
🧐 Resolution Behavior
You can call getGetterMap() / getSetterMap() in two ways:
-
Without property list: Returns a full canonical map using camelCase keys. If both a public property (e.g.
my_prop) and a corresponding getter (getMyProp()) exist, only the getter will be included to avoid duplication and ensure value transformation logic is preserved.$map = PropAccess::getGetterMap($entity); $map['myProp']($entity); // uses getMyProp(), not $entity->my_prop
-
With a property list: Allows access to both public properties and getter/setter methods via multiple aliases:
foo_bar→ accesses the public property (if available)fooBar→ accesses the getter/setter method (if available)
[$directSetter, $indirectSetter] = PropAccess::getSetterMap($myObj, ['foo_bar', 'fooBar']); $directSetter($myObj, 'A'); // -> $myObj->foo_bar = 'A'; $indirectSetter($myObj, 'B'); // -> $myObj->setFooBar('B');
🔌 Custom Accessor Resolvers
Resolvers can be registered to override or extend behavior:
PropAccess::bootDefaultResolvers(); // Registers built-in property/method resolvers PropAccess::registerGetterResolver(new MyCustomGetterResolver()); PropAccess::registerSetterResolver(new MyCustomSetterResolver());
Later-registered resolvers are tried first. If ->supports($object) returns false, fallback continues down the chain.
🧬 CaseConverter Utility
CaseConverter::toCamel('user_name'); // "userName" CaseConverter::toPascal('user_name'); // "UserName" CaseConverter::toSnake('UserName'); // "user_name" CaseConverter::toKebab('UserName'); // "user-name" CaseConverter::toUpperSnake('UserName'); // "USER_NAME"
You can also use the generic method:
CaseConverter::to('camel', 'foo_bar'); // Equivalent to toCamel()
🔍 AccessorProxy Helper
Need array-style access to object properties? AccessorProxy wraps an object and exposes property access via ArrayAccess, Traversable, and Countable.
use Nandan108\PropAccess\AccessorProxy; $proxy = AccessorProxy::getFor($user); // read-only by default echo $proxy['firstName']; // -> $user->getFirstName() $proxy['lastName'] = 'Smith'; // throws LogicException (read-only) $rwProxy = AccessorProxy::GetFor($user, readOnly: false); $rwProxy['lastName'] = 'Smith'; // works if setLastName() or $lastName is available
Includes convenience methods:
$proxy->toArray(); // ['firstName' => 'John', ...] $proxy->readableKeys(); // ['firstName', 'lastName', ...] $proxy->writeableKeys();
Use AccessorProxy::getFor() to fail gracefully:
$proxy = AccessorProxy::getFor($target); if (!$proxy) { // target does not support accessors }
📖 See docs/AccessorProxy.md for full reference.
✅ Quality
- ✅ 100% test coverage
- ✅ Psalm level 1
- ✅ Zero dependencies
MIT License © nandan108
统计信息
- 总下载量: 95
- 月度下载量: 0
- 日度下载量: 0
- 收藏数: 0
- 点击次数: 0
- 依赖项目数: 2
- 推荐数: 0
其他信息
- 授权协议: MIT
- 更新时间: 2025-06-11