bypassflow/value-kit の accessor と structure ヘルパーを、対象データの性質ごとに使い分けるための補助文書です。利用者向けの入口は ArrayPathAccessor を正本としつつ、厳密版、object 専用版、mixed ヘルパー、Structure 系をどう選ぶかをまとめます。
ArrayPathAccessor は、配列系データを普段使いで触るための利用者向け正本 accessor です。array と ArrayAccess の両方を受けます。
use bypassflow\ValueKit\Access\ArrayPathAccessor;
use ArrayObject;
$payload = new ArrayObject([
'user' => ['name' => 'alice'],
]);
$name = ArrayPathAccessor::get($payload, ['user', 'name']);ArrayAccess は array と同じ形で使えますが、存在判定は offsetExists() と isset() の実装に従います。class 側の実装次第で native array と差が出ることがあるため、厳密に native array へ寄せたい場合は StrictArrayPathAccessor を使います。
4 種 accessor の差分を最初に把握したい時は、対象型と途中パス生成の違いを見ると選びやすくなります。
ArrayPathAccessor- 利用者向けの正本です
array/ArrayAccessを受けます- 途中パスは配列で生成します
StrictArrayPathAccessor- native
arrayのみを受けます - 途中パスは配列で生成します
- native
ObjectPathAccessor- object public property のみを受けます
- magic method や private / protected property は扱いません
stdClassの途中パスは object 連鎖で生成します
PathAccessor- mixed ヘルパーです
array/ArrayAccess/ object public property を受けます- mixed payload を 1 本で辿りたい時にだけ選びます
stdClassの途中パスは object 連鎖で生成します
Structure 系は、パス 1 本を読む代わりに全体の形を変えたい時に選びます。用途ごとに 3 本へ分かれています。
KeyFlattener- nested
arrayを flat key/value へ潰します - 一覧化や field map 生成に向きます
- nested
RecursiveFilter- nested value 全体へ predicate をかけます
- cleanup や export 前の不要値除去に向きます
NestedGrouper- row list を grouped map へ再構成します
- row shaping や grouped report に向きます
Structure 系では、ヘルパーごとに返り値の形が異なります。使い分けを先に固定すると迷いにくくなります。
KeyFlattener- 平坦な key map
- path/value の組
RecursiveFilterkeepStdClass()の同形返却keep()/keepObjectAsArray()の配列返却
NestedGroupergrouped listgrouped one-map
Structure 系の公開語彙は、なるべく skip、normalize、keep first、keep last、throw on collision に寄せています。ヘルパーごとに挙動は違っても、説明語を揃えておくと選び分けやすくなります。
StrictArrayPathAccessor は、native array だけに入力を絞りたい時に使います。ArrayAccess は受けません。
use bypassflow\ValueKit\Access\StrictArrayPathAccessor;
$payload = [
'user' => ['name' => 'alice'],
];
$updated = StrictArrayPathAccessor::set($payload, ['user', 'name'], 'bob');ObjectPathAccessor は、object public property だけを辿りたい時の特化版です。stdClass では途中 path の生成も行えます。
use bypassflow\ValueKit\Access\ObjectPathAccessor;
$payload = (object) [
'user' => (object) ['name' => 'alice'],
];
$name = ObjectPathAccessor::get($payload, ['user', 'name']);この accessor は public property のみを対象にします。magic method、private / protected property、reflection 的な access は行いません。
PathAccessor は、array、ArrayAccess、object public property が混在するデータを 1 本で辿りたい時の下位ヘルパーです。公開面の最初の入口というより、mixed payload をそのまま扱う必要がある時の選択肢として使います。
use bypassflow\ValueKit\Access\PathAccessor;
$payload = (object) [
'user' => ['name' => 'alice'],
];
$name = PathAccessor::get($payload, ['user', 'name']);KeyFlattener は、nested array 全体を平坦な key/value へ潰したい時の Structure 系の入口です。パス 1 本を読むのではなく、全体の形を一覧化したい場面で使います。
use bypassflow\ValueKit\Structure\KeyFlattener;
$dot = KeyFlattener::dot([
'payload' => [
'user' => ['name' => 'alice'],
],
]);
$paths = KeyFlattener::paths([
'payload' => [
'roles' => ['admin', 'editor'],
],
]);dot() は平坦な key map を返し、paths() は path/value の組の list を返します。empty array は leaf として保持します。flatten() を使うと separator、leaf transform、throw on collision policy を切り替えられ、escaped() を使うと escape 付き key string を返せます。
dot key はパス要素を . で連結した表現です。そのため、要素自体に . を含む場合は見た目の曖昧さが残ります。escaped() はこの曖昧さを緩和する separator escape ヘルパーです。reversible encoding はまだ別軸で、必要なら KeyFlattener 本体ではなく別 helper として切り出す余地があります。
root や branch には array、走査可能な ArrayAccess、object public property を使えます。ArrayAccess は iteration できる実装を前提にしています。
dot()、flatten()、escaped() は平坦な key map を返すメソッド群です。最短では dot() を使い、separator や collision policy を触りたい時だけ flatten()、separator escape が必要な時だけ escaped() を選ぶ形が基本です。
paths() は path/value の組を返すメソッドです。フラットな文字列 key ではなく path list をそのまま扱いたい時だけこちらを選びます。
RecursiveFilter は、nested value 全体へ predicate をかけて不要 leaf を落としたい時のヘルパーです。汎用の keep() と、よく使う fixed helper を用意しています。
use bypassflow\ValueKit\Structure\RecursiveFilter;
$filtered = RecursiveFilter::removeNullAndEmptyString([
'payload' => [
'name' => '',
'email' => null,
'active' => true,
],
]);keep() の predicate は leaf 値だけに適用します。branch が filter の結果として空になった場合は削除し、元から空の array leaf だけは preserveEmptyArrays 引数で保持できます。branch 自体にも policy を掛けたい時は branchPredicate を使います。fixed helper として removeFalsy()、removeEmpty() も使えます。
object support は返却形を分けています。
keepObjectAsArray()- object public property を読んで配列で返します
keepStdClass()stdClass-only rebuildです- nested branch には
arrayとstdClassだけを許可します
branchPredicate のシグネチャは fn (array $branch, array $path, bool $explicitlyEmpty): bool です。
keep()、keepObjectAsArray()、keepStdClass() は基本 keep メソッド群です。keep() は array 正本、keepObjectAsArray() は object public property を読んで配列で返す variant、keepStdClass() は同じ形を維持したい時の variant として使い分けます。
removeNull()、removeEmptyString()、removeNullAndEmptyString()、removeFalsy()、removeEmpty() は固定 policy メソッド群です。custom predicate を書かずに固定 policy で掃除したい時に使います。
NestedGrouper は、row list を group key の組み合わせで nested map へ再構成したい時のヘルパーです。grouped list と grouped one-map の返り方を持ち、strict な groupBy() に加えて、missing row を飛ばす variant、keep first、keep last、non-scalar key を正規化する variant も使えます。
use bypassflow\ValueKit\Structure\NestedGrouper;
$grouped = NestedGrouper::groupBy(
[
['group' => 'staff', 'status' => 'active', 'name' => 'alice'],
['group' => 'staff', 'status' => 'inactive', 'name' => 'bob'],
],
['group', 'status'],
);selector は row 内の key、key path、または row を受ける callable を使えます。公開面の正本は path selector で、callable selector は寛容対応です。row は array、走査可能な ArrayAccess、object public property を受けます。strict 系では missing path は default bucket へ落とさず例外にし、group key も int|string に固定します。必要なら groupBySkippingMissing()、groupByNormalized()、groupOneBy()、groupLastBy() で policy を切り替えられます。group order は PHP 配列の insertion order をそのまま保持します。
groupBy()、groupBySkippingMissing()、groupByNormalized() は grouped list 系メソッドです。row list をそのまま grouped list へ落としたい時の正本で、skip missing と normalize key はこの系統側の policy variant です。
groupOneBy()、groupOneBySkippingMissing()、groupLastBy()、groupLastBySkippingMissing() は grouped one-map 系メソッドです。groupOneBy() は keep first、groupLastBy() は keep last を選ぶ variant として扱います。
存在判定では、パスの存在と isset() 相当の判定を分けています。
use bypassflow\ValueKit\Access\PathAccessor;
$payload = ['user' => ['name' => null]];
PathAccessor::existsPath($payload, ['user', 'name']); // true
PathAccessor::issetPath($payload, ['user', 'name']); // false
PathAccessor::has($payload, ['user', 'name']); // trueパス配列は list<int|string> を正本としますが、実装は寛容です。非 list 配列を渡した場合も array_values() で詰め直して処理するため、連想配列パスでは key ではなく value が要素として使われます。
set() と remove() は、対象型に応じた accessor を選ぶと挙動が読みやすくなります。普段使いは ArrayPathAccessor、厳密な型制約を掛けたい時は StrictArrayPathAccessor や ObjectPathAccessor、mixed payload をまとめて扱う必要がある時だけ PathAccessor を選ぶのが基本です。
use bypassflow\ValueKit\Access\ArrayPathAccessor;
$payload = ['user' => ['name' => 'alice', 'email' => 'alice@example.com']];
$updated = ArrayPathAccessor::remove($payload, ['user', 'email']);