dmitrijs-brujevs/data-object
Composer 安装命令:
composer require dmitrijs-brujevs/data-object
包简介
Path-based in-memory data container with nested array access via slash-separated node paths.
README 文档
README
A lightweight, path-based in-memory data container for PHP 8.2+.
Stores data in a nested array and provides access via slash-separated node paths. No dependencies. No magic beyond what is documented.
Why this library?
- You receive config, API responses, or form data as nested arrays and want clean, readable access without
$data['user']['address']['city'] ?? nullchains - You want dot/slash-path notation with
isset-safe existence checks - You need a minimal, subclassable value object with no framework coupling
Requirements
- PHP 8.2+
ext-json
Installation
composer require dmitrijs-brujevs/data-object
Quick Start
use DmitrijsBrujevs\DataObject\DataObject; $obj = DataObject::fromArray([ 'user' => [ 'name' => 'John', 'role' => 'admin', 'address' => [ 'city' => 'Riga', 'country' => 'Latvia', ], ], ]); $obj->get('user/name'); // "John" $obj->get('user/address/city'); // "Riga" $obj->has('user/role'); // true $obj->is('user/role', 'admin'); // true $obj->set('user/age', 30); $obj->delete('user/role'); $obj->getOrDefault('user/email', 'n/a'); // "n/a" — key is absent
Creating an Instance
Use the explicit factory methods when the input format is known:
// from array $obj = DataObject::fromArray(['key' => 'value']); // from JSON string $obj = DataObject::fromJson('{"key":"value"}'); // from PHP serialized string (objects disallowed — see Security section) $obj = DataObject::fromSerialized(serialize(['key' => 'value']));
The constructor also accepts all three formats via auto-detection:
$obj = new DataObject(['key' => 'value']); $obj = new DataObject('{"key":"value"}'); $obj = new DataObject(serialize(['key' => 'value']));
An InvalidArgumentException is thrown if the string is neither valid JSON nor a serialized array.
Path Notation
Each segment of a path corresponds to a key in the nested structure.
The default delimiter is /, customisable per instance.
"user/address/city" → $data['user']['address']['city']
"config/db/port" → $data['config']['db']['port']
API Reference
get(string $node = ''): mixed
Returns the value at the given path.
- Nested array → returned as a new
DataObjectinstance (same concrete class) - Missing path → returns
null - No arguments → returns
$this(root)
$obj->get('user/name'); // "John" $obj->get('user'); // DataObject { name: "John", ... } $obj->get('user/missing'); // null $obj->get(); // $this
null vs missing:
get()returnsnullfor both a missing path and an explicitnullvalue. Usehas()to distinguish them, or usegetOrDefault().
getOrDefault(string $node, mixed $default = null): mixed
Returns the value at the given path, or $default if the node does not exist.
Unlike get(), this correctly distinguishes between a missing node and an explicit null value:
$obj->set('role', null); $obj->getOrDefault('role', 'guest'); // null — key exists, value is null $obj->getOrDefault('missing', 'guest'); // "guest" — key does not exist
has(string $node): bool
Returns true if the node exists, regardless of its value. Uses array_key_exists semantics.
$obj->set('role', null); $obj->has('role'); // true — key exists, value is null $obj->has('email'); // false — key is absent $obj->has(''); // true — root always exists
is(string $node, mixed $value): bool
Strict equality check (===). Returns false if the node does not exist.
$obj->set('score', 10); $obj->set('role', null); $obj->is('score', 10); // true $obj->is('score', '10'); // false — int !== string $obj->is('role', null); // true — key exists, value is null $obj->is('missing', null); // false — key does not exist
Note:
is('missing', null)returnsfalse(changed in 2.1.0 — previously returnedtrue). Usehas()orgetOrDefault()if the old behaviour was relied upon.
set(string|int $node, mixed $value): static
Sets a value at the given path. Intermediate nodes are created automatically.
If an intermediate node holds a non-array value, it is replaced with an array.
Returns $this for fluent chaining.
$obj->set('user/name', 'Jane'); $obj->set('user/address/zip', '1010'); $obj->set('user/role', null); $obj->set('a', 1)->set('b', 2)->set('c', 3);
add(array $array, string $node = ''): static
Recursively merges a nested array into the object.
Existing values at the same paths are overwritten.
Empty arrays are stored as-is — get() on that path returns an empty DataObject.
$obj->add(['user' => ['name' => 'John', 'age' => 30]]); $obj->get('user/name'); // "John" // with a path prefix $obj->add(['host' => 'localhost', 'port' => 3306], 'config/db'); $obj->get('config/db/host'); // "localhost" // empty array is stored, not ignored $obj->add(['tags' => []]); $obj->has('tags'); // true $obj->get('tags'); // DataObject (empty)
delete(string $node): static
Removes the value at the given path. Only the final segment is removed; parent nodes and siblings remain intact. No-op for non-existent paths.
$obj->delete('user/role'); $obj->has('user/role'); // false $obj->get('user/name'); // "John" — siblings intact $obj->delete('user/age')->delete('user/email'); // fluent
toArray(): array
Returns the internal storage as a plain nested PHP array.
$obj->toArray(); // ['user' => ['name' => 'John', 'age' => 30]]
toJson(int $flags, int $depth): string
Returns the data encoded as a JSON string.
Default flags: JSON_THROW_ON_ERROR | JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES.
$obj->toJson(); // {"user":{"name":"Иван","url":"https://example.com"}} $obj->toJson(JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE);
serialize(): string
Returns the data as a PHP serialized string.
$serialized = $obj->serialize(); $restored = DataObject::fromSerialized($serialized);
Magic camelCase Methods
Any method prefixed with get, set, has, is, or delete is resolved
by __call() at runtime. The name is split on uppercase letters and joined
with the delimiter to form a path.
$obj->getUserName() // → get('user/name') $obj->setUserName('Jane') // → set('user/name', 'Jane') $obj->hasUserRole() // → has('user/role') $obj->isUserRole('admin') // → is('user/role', 'admin') $obj->deleteUserRole() // → delete('user/role') $obj->getUserAddressCity() // → get('user/address/city')
Unknown prefixes throw BadMethodCallException (changed in 2.1.0 — previously returned null).
Limitations:
- Consecutive uppercase letters are split per character:
getURLPath()→get('u/r/l/path'). Use explicit path strings for such keys. - Multi-word method names (
getOrDefault) cannot be dispatched via magic — the parser only recognises single-word prefixes.
Iteration
DataObject implements Iterator. Nested arrays are automatically wrapped
in DataObject instances at each level.
foreach ($obj as $key => $value) { // $value is DataObject if the element is a nested array } // nested foreach works across any depth foreach ($obj as $continent => $countries) { foreach ($countries as $country => $info) { echo $info->get('capital'); } }
Custom Delimiter
$obj = DataObject::fromArray(['user' => ['name' => 'John']], delimiter: '.'); $obj->get('user.name'); // "John" $obj->set('user.age', 30);
Subclassing
DataObject is designed to be subclassed. All factory methods and internal
wrapping use new static(), so nested arrays and iterator values are wrapped
in the concrete subclass.
class UserObject extends DataObject {} $user = UserObject::fromArray(['name' => 'John', 'roles' => ['admin', 'editor']]); $user->get('roles'); // UserObject instance, not DataObject
Public method overrides in subclasses take full precedence — PHP routes them
directly without going through __call().
Security — Serialized Input
fromSerialized() and the constructor's auto-detection both use
unserialize($data, ['allowed_classes' => false]).
This means:
- No PHP objects are instantiated during deserialization — gadget-chain attacks are blocked
- Only arrays are accepted; anything else throws
InvalidArgumentException - PHP warnings from malformed strings are caught via a temporary error handler, not
@
Only pass serialized data from sources you control. Even with allowed_classes = false,
deserializing untrusted user input is not recommended practice.
Running Locally
composer install composer test # PHPUnit composer stan # PHPStan level 8 composer cs # PHP-CS-Fixer (dry-run) composer cs:fix # PHP-CS-Fixer (apply) composer check # stan + cs + test
License
MIT
dmitrijs-brujevs/data-object 适用场景与选型建议
dmitrijs-brujevs/data-object 是一款 基于 PHP 开发的 Composer 扩展包,目前已累计 3 次下载、GitHub Stars 达 0, 最近一次更新时间为 2026 年 04 月 12 日, 在 PHP 生态内属于活跃度较高的组件。
它主要适用于以下技术方向: 「container」 「path」 「data」 「array」 「helper」 「dot-notation」 等业务场景。在实际项目中,围绕这些方向常见需要落地的问题包括:接口对接、性能调优、并发安全、与既有框架(Laravel / ThinkPHP / Yii / Webman 等)的兼容适配,以及生产环境的日志埋点与稳定性保障。
我们在过去多个企业项目中使用过 dmitrijs-brujevs/data-object 或与其功能相近的方案,如果你在选型或落地过程中遇到问题,例如 版本兼容、二次改造、私有化封装、与内部系统对接、生产 BUG 排查,欢迎联系我们协助评估。
基于 dmitrijs-brujevs/data-object 在你已有业务上做功能扩展、字段裁剪、UI 适配、与内部账号 / 权限 / 日志系统的深度对接。
线上偶发问题、内存泄漏、慢查询、并发异常等排查修复;针对高流量场景做缓存、队列、索引层面的调优。
承接完整的项目从需求 → 设计 → 开发 → 上线 → 长期运维;也可按月提供技术保姆服务。
与 dmitrijs-brujevs/data-object 相关的其它包
同方向 / 同关键字的高下载量 PHP Composer 包推荐,方便对比选型:
Shoot aims to make providing data to your templates more manageable
JSONPath implementation for querying and updating JSON objects with support for json flattening into a table
Adds the EDTF data type to Wikibase
A simple library that allows transform any kind of data to native php data or whatever
A fast and intuitive dependency injection container.
The InstantConfigurationCopy module provides easy way to copy configuration field information for admin in back office Magento 2.
统计信息
- 总下载量: 3
- 月度下载量: 0
- 日度下载量: 0
- 收藏数: 0
- 点击次数: 44
- 依赖项目数: 0
- 推荐数: 0
其他信息
- 授权协议: MIT
- 更新时间: 2026-04-12