承接 nandan108/prop-access 相关项目开发

从需求分析到上线部署,全程专人跟进,保证项目质量与交付效率

邮箱:yvsm@zunyunkeji.com | QQ:316430983 | 微信:yvsm316

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

CI Coverage Style Packagist

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)
  • 🧼 CaseConverter utility 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:

  1. 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
  2. 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

GitHub 信息

  • Stars: 0
  • Watchers: 0
  • Forks: 0
  • 开发语言: PHP

其他信息

  • 授权协议: MIT
  • 更新时间: 2025-06-11