焦点 / 数据
用于处理非结构化数据(如JSON)的工具集合
Requires
- php: ^8.2
- mtdowling/jmespath.php: ^2.7
- psr/http-message: ^1.0 || ^2.0
Requires (Dev)
- doctrine/coding-standard: ^12.0
- ergebnis/composer-normalize: ^2.39
- nyholm/psr7: ^1.8
- phpunit/phpunit: ^10.4
README
用于处理非结构化数据(如JSON)的工具集合
安装
安装并使用此包的最佳方式是使用 composer
composer require focus/data
用法
最基本的使用是 KeyedDataObject
,它封装对象和 KeyedDataArray
,它封装数组
use Focus\Data\KeyedData\KeyedDataFactory; $value = [ 'user' => [ 'name' => 'Susan Smith', 'email' => 'susan@example.com', 'hobbies' => [ 'football', 'swimming', 'reading', ], 'deactivated_at' => null, ], ]; // Will create either KeyedDataObject or KeyedDataArray, depending on the value $data = KeyedDataFactory::from($value);
一旦您有一个数据实例,您可以通过使用点路径来访问值
$name = $data->get(path: 'user.name'); // Susan Smith $email = $data->get(path: 'user.email'); // susan@example.com
不存在的值将返回为 null
$phone = $data->get(path: 'user.phone'); // null
支持使用 JMESPath 表达式,通过使用 search() 方法
$sports = $data->search(path: "user.hobbies[? contains(@, 'ball')]"); // ['football']
即使值是 null
,也可以检查路径的存在
$deactivated = $data->has(path: 'user.deactivated_at'); // true
JSON 数据
JsonData
对象是一个代理,具有用于从 JSON 字符串以及 PSR-7 RequestInterface
、ServerRequestInterface
和 ResponseInterface
对象创建数据实例的工厂方法
use Focus\Data\JsonData; /** @var Psr\Http\Message\ServerRequestInterface $request */ $request = $app->request(); $data = JsonData::fromRequest($request);
为 JsonData
提供了三种工厂方法
fromString()
从 JSON 字符串创建数据fromRequest()
从 PSR-7(服务器)请求创建数据fromResponse()
从 PSR-7 响应创建数据
当使用 ServerRequestInterface
对象调用 JsonData::fromRequest()
时,默认会使用 getParsedBody()
的值。要禁用此行为,请使用
$data = JsonData::fromRequest($request, useParsedBody: false);
当使用 getParsedBody()
时,请记住,大多数 ServerRequestInterface
对象会使用 associative: true
解码请求体,生成一个数组。如果您希望 JsonData->value
是一个对象而不是数组,请将 ServerRequestInterface
配置为使用 associative: false
(json_decode()
的默认值)解码请求体
常见问题解答
这些是关于此包的使用和设计的常见问题。
为什么 has() 对 null 值返回 true?
这允许检测输入值,这些值不应该被覆盖。例如,如果应用程序将 deactivated_at
时间戳设置为表示用户已离职,它可能还需要能够通过设置 deactivated_at: null
来重新激活用户
if ($data->get(path: 'user.deactivated_at')) { $this->userRepository->deactivate( id: $data->get(path: 'user.id'), timestamp: $data->get(path: 'user.deactivated_at'), ); } elseif ($data->has(path: 'user.deactivated_at')) { $this->userRepository->activate( id: $data->get(path: 'user.id'), ); }
如果 has() 对 null 值不返回 true,则检测 null 值的存在将是不可能的,因为 get() 对于未定义的路径返回 null。
为什么存在数据接口?
细心的观察者会注意到 KeyedData
实现了一个 Data
接口,以及存在 DataProxy
抽象类的存在。这允许通过使用 代理对象 来定制实现,尽管 KeyedData
是一个 final readonly
类,以满足 开闭原则。
默认情况下,DataProxy
对象会将所有调用直接转发到源 Data
对象。这允许自定义任何方法的行为,而无需实现完整的 Data
接口。例如,这将修改 get() 方法以将 false
值视为 null
。
use Focus\Data\Data; use Focus\Data\DataProxy; final class MyData extends DataProxy { public function get(string $path): mixed { $value = $this->source()->get($path); if ($value === false) { return null; } return $value; } }