sbwerewolf/language-specific 问题修复 & 功能扩展

解决BUG、新增功能、兼容多环境部署,快速响应你的开发需求

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

sbwerewolf/language-specific

Composer 安装命令:

composer require sbwerewolf/language-specific

包简介

Read nested arrays safely and cast values predictably in PHP 8.4+

README 文档

README

Packagist Version Packagist Downloads License CI Static Analysis Test Coverage

Read nested arrays safely and cast values predictably in PHP 8.4+

Use it when you need to:

  • read nested arrays without long isset() (??) chains
  • normalize request/config payloads with explicit defaults
  • keep the “missing value” state visible instead of leaking null everywhere

Install

composer require sbwerewolf/language-specific

Quick example

use SbWereWolf\LanguageSpecific\AdvancedArrayFactory;

$payload = [
    'user' => [
        'id' => '42',
        'role' => 'admin',
    ],
];
$data = new AdvancedArrayFactory()->makeAdvancedArray($payload);

$userId = $data->pull('user')->get('id')->int(); // 42
$timezone = $data->pull('user')->get('timezone')->default('UTC')->str(); // 'UTC'
// -- OR --
$user = $data->pull('user');

$userId = $user->get('id')->int(); // 42
$timezone = $user->get('timezone')->default('UTC')->str(); // 'UTC' 

Code test coverage

Codecov graph

Quick navigation

Killer features

1. Safe nested config access

Use AdvancedArray when you need to walk through deeply nested arrays without isset() chains and still keep explicit control over missing values.

use SbWereWolf\LanguageSpecific\AdvancedArrayFactory;

$factory = new AdvancedArrayFactory();
$config = $factory->makeAdvancedArray([
    'app' => [
        'cache' => [
            'driver' => 'redis',
        ],
    ],
]);

$driver = $config
    ->pull('app')
    ->pull('cache')
    ->get('driver')
    ->default('file')
    ->str();
    
$driver; // 'redis'

$fallback = $config
    ->pull('app')
    ->pull('queue')
    ->get('driver')
    ->default('sync')
    ->str();

$fallback; // 'sync'

Continue with AdvancedArray.

2. HTTP payload parsing

Use CommonValue conversions to normalize request payloads without sprinkling casts across the whole handler.

use SbWereWolf\LanguageSpecific\AdvancedArrayFactory;

$factory = new AdvancedArrayFactory();
$payload = $factory->makeAdvancedArray([
    'user' => [
        'id' => '42',
        'is_admin' => '1',
    ],
]);

$userId = $payload->pull('user')->get('id')->int(); // 42
$isAdmin = $payload->pull('user')->get('is_admin')->bool(); // true

$timezone = $payload->pull('user')->get('timezone')->default('UTC')->str();
// 'UTC'

Continue with AdvancedArray and CommonValue.

3. Legacy arrays normalization

Use factories to turn inconsistent old-style data into one predictable API.

use SbWereWolf\LanguageSpecific\Collection\ArrayFactory;

$factory = new ArrayFactory();
$legacy = $factory->makeCommonArray('legacy-value');

$legacy->hasAny(); // true
$legacy->getAny()->str(); // 'legacy-value'
$legacy->get(0)->str(); // 'legacy-value'

Continue with ArrayFactory and CommonArray.

AdvancedArray

Back to killer features.

Create an AdvancedArray with makeAdvancedArray()

Use AdvancedArrayFactory as the main entry point for nested data.

use SbWereWolf\LanguageSpecific\AdvancedArrayFactory;

$factory = new AdvancedArrayFactory();
$data = $factory->makeAdvancedArray([
    'service' => [
        'name' => 'Billing',
    ],
]);

$data->isDummy(); // false
$data->pull('service')->get('name')->str(); // 'Billing'

pull() returns a nested AdvancedArrayInterface

pull() can return the first nested array or a specific nested array by key.

use SbWereWolf\LanguageSpecific\AdvancedArrayFactory;

$factory = new AdvancedArrayFactory();
$data = $factory->makeAdvancedArray([
    [
        'config' => [
            'env' => [
                'name' => 'production',
            ],
        ],
    ],
    'meta' => [
        'region' => 'eu',
    ],
]);

$data->pull()->pull('config')->pull('env')->get('name')->str(); // 'production'
$data->pull('meta')->get('region')->str(); // 'eu'

isDummy() marks a missing nested array

Missing nested arrays return a dummy object instead of throwing or leaking null.

use SbWereWolf\LanguageSpecific\AdvancedArrayFactory;

$factory = new AdvancedArrayFactory();
$data = $factory->makeAdvancedArray([
    'first' => [
        'A' => 1,
    ],
]);

$data->pull('first')->isDummy(); // false
$data->pull('missing')->isDummy(); // true

get() reads a value and keeps the missing-state visible

get() returns a CommonValueInterface, so you can inspect both the value and whether the key was actually present.

use SbWereWolf\LanguageSpecific\AdvancedArrayFactory;

$factory = new AdvancedArrayFactory();
$data = $factory->makeAdvancedArray([
    'name' => 'Mike',
    'salary' => 19999.99,
]);

$data->get('name')->str(); // 'Mike'
$data->get('salary')->int(); // 19999
$data->get('missing')->asIs(); // null
$data->get('missing')->isReal(); // false

getAny() returns the first value or a dummy for an empty collection

Use getAny() when any first available value is good enough.

use SbWereWolf\LanguageSpecific\AdvancedArrayFactory;

$factory = new AdvancedArrayFactory();
$filled = $factory->makeAdvancedArray([
    'first' => 'A',
    'second' => 'B',
]);

$filled->getAny()->str(); // 'A'
$filled->getAny()->isReal(); // true

$empty = $factory->makeAdvancedArray([]);

$empty->getAny()->asIs(); // null
$empty->getAny()->isReal(); // false

has() checks a specific key

Use has() when you want to know whether a given key exists before reading it.

use SbWereWolf\LanguageSpecific\AdvancedArrayFactory;

$factory = new AdvancedArrayFactory();
$data = $factory->makeAdvancedArray([
    0 => 'first',
    'next' => 2,
]);

$data->has(0); // true
$data->has('next'); // true
$data->has('missing'); // false

hasAny() checks whether the collection is not empty

Use hasAny() when you only care whether there is at least one item.

use SbWereWolf\LanguageSpecific\AdvancedArrayFactory;

$factory = new AdvancedArrayFactory();
$filled = $factory->makeAdvancedArray([
    'first' => 1,
]);

$filled->hasAny(); // true

$empty = $factory->makeAdvancedArray([]);
$empty->hasAny(); // false

arrays() iterates over nested arrays only

This is useful when you need to process nested lists without checking each item.

use SbWereWolf\LanguageSpecific\AdvancedArrayFactory;

$factory = new AdvancedArrayFactory();
$data = $factory->makeAdvancedArray([
    [
        'name' => 'first',
    ],
    [
        'name' => 'second',
    ],
    'tail',
]);

$names = [];
foreach ($data->arrays() as $nested) {
    $names[] = $nested->get('name')->str();
}

$names; // ['first', 'second']

values() iterates over non-array elements only

This is useful when the collection mixes nested arrays with plain scalar values.

use SbWereWolf\LanguageSpecific\AdvancedArrayFactory;

$factory = new AdvancedArrayFactory();
$data = $factory->makeAdvancedArray([
    [
        'skip' => true,
    ],
    'first',
    'next',
    'last',
]);

$values = [];
foreach ($data->values() as $value) {
    $values[] = $value->str();
}

$values; // ['first', 'next', 'last']

CommonValue

Back to killer features.

asIs() returns the stored value exactly as it is

Use asIs() when you want the original stored value without casting.

use SbWereWolf\LanguageSpecific\Value\CommonValueFactory;

$value = CommonValueFactory::makeCommonValue([
    'env' => 'prod',
]);

$value->asIs(); // ['env' => 'prod']

isReal() and default() make missing-state explicit

Use default() only for missing values; real values stay untouched.

use SbWereWolf\LanguageSpecific\Value\CommonValueFactory;

$dummy = CommonValueFactory::makeCommonValueAsDummy();

$dummy->isReal(); // false
$dummy->asIs(); // null
$dummy->default('fallback')->str(); // 'fallback'

$real = CommonValueFactory::makeCommonValue('real value');

$real->isReal(); // true
$real->default('fallback')->str(); // 'real value'

Scalar casts stay close to native PHP casting rules

Use the typed helpers when you want the cast at the point of reading.

use SbWereWolf\LanguageSpecific\Value\CommonValueFactory;

$value = CommonValueFactory::makeCommonValue('1.1');

$value->str(); // '1.1'
$value->int(); // 1
$value->double(); // 1.1
$value->bool(); // true

array() turns the current value into an array

This is especially useful when you want one array-shaped read path.

use SbWereWolf\LanguageSpecific\Value\CommonValueFactory;

$stringValue = CommonValueFactory::makeCommonValue('release');
$stringValue->array(); // ['release']

$arrayValue = CommonValueFactory::makeCommonValue([
    'env' => 'prod',
]);
$arrayValue->array(); // ['env' => 'prod']

object() returns the stored object value

When the stored value is already an object, object() returns it unchanged.

use SbWereWolf\LanguageSpecific\Value\CommonValue;
use SbWereWolf\LanguageSpecific\Value\CommonValueFactory;

$inner = CommonValueFactory::makeCommonValue(1);
$outer = CommonValueFactory::makeCommonValue($inner);
$object = $outer->object();

$object instanceof CommonValue; // true
$object->asIs(); // 1

type() shows all native gettype() results used by this library

This example is meant to be read without running it, so every visible result is listed explicitly.

use SbWereWolf\LanguageSpecific\Value\CommonValueFactory;

$stream = fopen('php://memory', 'r');

$results = [
    CommonValueFactory::makeCommonValue(null)->type(), //'NULL'
    CommonValueFactory::makeCommonValue(false)->type(), //'boolean'
    CommonValueFactory::makeCommonValue(0)->type(), //'integer'
    CommonValueFactory::makeCommonValue(0.1)->type(), //'double'
    CommonValueFactory::makeCommonValue('a')->type(), //'string'
    CommonValueFactory::makeCommonValue([])->type(), //'array'
    CommonValueFactory::makeCommonValue((object) null)->type(), //'object'
    CommonValueFactory::makeCommonValue($stream)->type(), //'resource'
];

fclose($stream);

$results[] = CommonValueFactory::makeCommonValue($stream)->type(); 
// 'resource (closed)'

$results;
/*
[
    'NULL',
    'boolean',
    'integer',
    'double',
    'string',
    'array',
    'object',
    'resource',
    'resource (closed)',
]
*/

class() shows all native get_debug_type() results used by this library

This example includes scalars, arrays, named classes, anonymous classes, resources, and closed resources.

use SbWereWolf\LanguageSpecific\Value\CommonValueFactory;

final class DocumentationNamedExampleClass
{
}

$stream = fopen('php://memory', 'r');
$anonymous = new class () {
};

$results = [
    CommonValueFactory::makeCommonValue(null)->class(), // null
    CommonValueFactory::makeCommonValue(false)->class(), // bool
    CommonValueFactory::makeCommonValue(0)->class(), // int
    CommonValueFactory::makeCommonValue(0.1)->class(), // float
    CommonValueFactory::makeCommonValue('a')->class(), // string
    CommonValueFactory::makeCommonValue([])->class(), // array
    CommonValueFactory::makeCommonValue((object) null)->class(), // stdClass
    
    CommonValueFactory::makeCommonValue(new DocumentationNamedExampleClass())->class(), 
    // DocumentationNamedExampleClass
    
    CommonValueFactory::makeCommonValue($anonymous)->class(), // class@anonymous
    CommonValueFactory::makeCommonValue($stream)->class(), // resource (stream)
];

fclose($stream);

$results[] = CommonValueFactory::makeCommonValue($stream)->class(); 
// resource (closed)

$results;
/*
[
    'null',
    'bool',
    'int',
    'float',
    'string',
    'array',
    'stdClass',
    'DocumentationNamedExampleClass',
    'class@anonymous',
    'resource (stream)',
    'resource (closed)',
]
*/

ArrayFactory

Back to killer features.

makeBaseArray() wraps any value into a predictable iterable array object

Use BaseArray when you only need the raw iterable container behavior.

use SbWereWolf\LanguageSpecific\Collection\ArrayFactory;

$factory = new ArrayFactory();
$data = $factory->makeBaseArray('legacy-value');

$data->raw(); // ['legacy-value']

makeCommonArray() adds get() and has() on top of the same normalized data

Use CommonArray when the data is mostly flat and you want value wrappers.

use SbWereWolf\LanguageSpecific\Collection\ArrayFactory;

$factory = new ArrayFactory();
$data = $factory->makeCommonArray([
    'id' => '42',
    'enabled' => '1',
]);

$data->get('id')->int(); // 42
$data->get('enabled')->bool(); // true

CommonArray

Back to killer features.

get() reads a specific value

get() returns a CommonValueInterface, so missing keys stay observable.

use SbWereWolf\LanguageSpecific\Collection\ArrayFactory;

$factory = new ArrayFactory();
$data = $factory->makeCommonArray([
    'name' => 'Alice',
    'age' => '31',
]);

$data->get('name')->str(); // 'Alice'
$data->get('age')->int(); // 31
$data->get('missing')->isReal(); // false

getAny() returns the first value or a dummy for an empty collection

This is the flat-array equivalent of AdvancedArray::getAny().

use SbWereWolf\LanguageSpecific\Collection\ArrayFactory;

$factory = new ArrayFactory();
$filled = $factory->makeCommonArray([
    'first' => 'A',
    'second' => 'B',
]);
$filled->getAny()->str(); // 'A'

$empty = $factory->makeCommonArray([]);
$empty->getAny()->isReal(); // false

has() checks a specific key

Use it when you want a lightweight presence check before reading the value.

use SbWereWolf\LanguageSpecific\Collection\ArrayFactory;

$factory = new ArrayFactory();
$data = $factory->makeCommonArray([
    0 => 'first',
    'next' => 2,
]);

$data->has(0); // true
$data->has('next'); // true
$data->has('missing'); // false

hasAny() checks whether the collection is not empty

Use it when you only need to know whether the collection contains any item.

use SbWereWolf\LanguageSpecific\Collection\ArrayFactory;

$factory = new ArrayFactory();
$filled = $factory->makeCommonArray([
    'first' => 1,
]);
$filled->hasAny(); // true

$empty = $factory->makeCommonArray([]);
$empty->hasAny(); // false

BaseArray

Back to killer features.

raw() returns the original normalized array

Use raw() when you need the plain array back without wrappers.

use SbWereWolf\LanguageSpecific\Collection\ArrayFactory;

$factory = new ArrayFactory();
$data = $factory->makeBaseArray([
    0 => 'first',
    'index' => 20,
    3 => 'last',
]);

$data->raw();
/*
[
    0 => 'first',
    'index' => 20,
    3 => 'last',
]
*/

Factory helpers

Back to killer features.

makeDummyAdvancedArray() creates a missing nested-array placeholder

Use it when you need a manual dummy object that behaves like a missing nested array.

use SbWereWolf\LanguageSpecific\AdvancedArrayFactory;

$factory = new AdvancedArrayFactory();
$dummy = $factory->makeDummyAdvancedArray();

$dummy->isDummy(); // true
$dummy->hasAny(); // false

makeCommonValue() wraps any value into a CommonValueInterface

Use it when you want the value-wrapper behavior without creating an array object.

use SbWereWolf\LanguageSpecific\Value\CommonValueFactory;

$value = CommonValueFactory::makeCommonValue([
    'region' => 'eu',
]);

$value->array()['region']; // 'eu'

makeCommonValueAsDummy() creates a missing-value placeholder

Use it when the missing-state itself is part of the control flow.

use SbWereWolf\LanguageSpecific\Value\CommonValueFactory;

$dummy = CommonValueFactory::makeCommonValueAsDummy();

$dummy->isReal(); // false
$dummy->default('fallback')->str(); // 'fallback'

Native PHP interfaces

Back to killer features.

These features are convenient, but they are not the main reason to use the library.

Read values with []

use SbWereWolf\LanguageSpecific\AdvancedArrayFactory;

$factory = new AdvancedArrayFactory();
$data = $factory->makeAdvancedArray([
    'name' => 'Billing',
    'active' => true,
]);

$data['name']->str(); // 'Billing'
$data['active']->bool(); // true

Iterate with foreach

use SbWereWolf\LanguageSpecific\AdvancedArrayFactory;

$factory = new AdvancedArrayFactory();
$data = $factory->makeAdvancedArray([
    'name' => 'Billing',
    'active' => true,
]);

$result = [];
foreach ($data as $key => $value) {
    $result[$key] = $value->asIs();
}

$result; // ['name' => 'Billing', 'active' => true]

Serialize the whole object with json_encode()

use SbWereWolf\LanguageSpecific\AdvancedArrayFactory;

$factory = new AdvancedArrayFactory();
$data = $factory->makeAdvancedArray([
    'name' => 'Billing',
    'flags' => [
        'active' => true,
    ],
]);

echo json_encode($data, JSON_PRETTY_PRINT | JSON_THROW_ON_ERROR);
/*
{
    "name": "Billing",
    "flags": {
        "active": true
    }
}
*/

Run tests

composer test

Documentation examples are executable in:

  • tests/unit/DocumentationExamplesTest.php

Contacts

Volkhin Nicholas
e-mail ulfnew@gmail.com
phone +7-902-272-65-35
Telegram @sbwerewolf

sbwerewolf/language-specific 适用场景与选型建议

sbwerewolf/language-specific 是一款 基于 PHP 开发的 Composer 扩展包,目前已累计 23.37k 次下载、GitHub Stars 达 3, 最近一次更新时间为 2019 年 10 月 26 日, 在 PHP 生态内属于活跃度较高的组件。

它主要适用于以下技术方向: 「php」 「config」 「arrays」 「type casting」 「composer package」 「nested arrays」 等业务场景。在实际项目中,围绕这些方向常见需要落地的问题包括:接口对接、性能调优、并发安全、与既有框架(Laravel / ThinkPHP / Yii / Webman 等)的兼容适配,以及生产环境的日志埋点与稳定性保障。

我们在过去多个企业项目中使用过 sbwerewolf/language-specific 或与其功能相近的方案,如果你在选型或落地过程中遇到问题,例如 版本兼容、二次改造、私有化封装、与内部系统对接、生产 BUG 排查,欢迎联系我们协助评估。

围绕 sbwerewolf/language-specific 我们能提供哪些服务?
定制开发 / 二次开发

基于 sbwerewolf/language-specific 在你已有业务上做功能扩展、字段裁剪、UI 适配、与内部账号 / 权限 / 日志系统的深度对接。

BUG 修复 & 性能优化

线上偶发问题、内存泄漏、慢查询、并发异常等排查修复;针对高流量场景做缓存、队列、索引层面的调优。

项目外包 & 长期维护

承接完整的项目从需求 → 设计 → 开发 → 上线 → 长期运维;也可按月提供技术保姆服务。

yvsm@zunyunkeji.com QQ:316430983 微信:yvsm316 西安尊云信息科技 · 专注 PHP / Go / 分布式系统研发

统计信息

  • 总下载量: 23.37k
  • 月度下载量: 0
  • 日度下载量: 0
  • 收藏数: 3
  • 点击次数: 19
  • 依赖项目数: 0
  • 推荐数: 0

GitHub 信息

  • Stars: 3
  • Watchers: 1
  • Forks: 1
  • 开发语言: PHP

其他信息

  • 授权协议: MIT
  • 更新时间: 2019-10-26