alexkart/typed-registry-laravel
Composer 安装命令:
composer require alexkart/typed-registry-laravel
包简介
Laravel integration for typed-registry with type-casting providers and facades
README 文档
README
Laravel integration for typed-registry following Laravel best practices for environment variable and configuration access.
Why?
Laravel's env() and config() helpers return mixed values, making strict type checking difficult. This package provides:
- Type-safe config access -
TypedConfigfacade andtypedConfig()helper with strict return types - Type-safe env access -
typedEnv()helper for use in config files only (following Laravel best practices) - String-preserving env access -
typedEnvString()helper for values that must stay strings (passwords, tokens) - Intelligent casting - Environment variables automatically cast from strings (
"8080"→8080,"1e3"→1000.0) - PHPStan ready - Works seamlessly with static analysis at max level
- Zero runtime overhead - Simple wrappers around Laravel's existing systems
Installation
composer require alexkart/typed-registry-laravel
Requires:
- PHP 8.3+
- Laravel 11+ or 12+ or 13+
The package uses Laravel's auto-discovery feature. The service provider and facade are registered automatically.
Quick Start
Environment Variables in Config Files
Following Laravel Best Practices: Environment variables should ONLY be accessed in config files, never directly in controllers or services.
// config/app.php return [ 'name' => typedEnv()->getStringOr('APP_NAME', 'Laravel'), 'debug' => typedEnv()->getBoolOr('APP_DEBUG', false), 'port' => typedEnv()->getIntOr('APP_PORT', 8080), // "8080" → 8080 'timeout' => typedEnv()->getFloatOr('TIMEOUT', 2.5), // "2.5" → 2.5 'max_items' => typedEnv()->getInt('MAX_ITEMS'), // Throws if missing ];
Configuration Access Everywhere
Use the TypedConfig facade or typedConfig() helper in controllers, services, and anywhere else:
use TypedRegistry\Laravel\Facades\TypedConfig; class UserController { public function index() { $perPage = TypedConfig::getInt('app.pagination.per_page'); $appName = TypedConfig::getString('app.name'); $features = TypedConfig::getStringList('app.enabled_features'); // Or use the helper $timeout = typedConfig()->getFloat('app.timeout'); } }
Features
typedEnv() Helper - For Config Files Only
Wraps Illuminate\Support\Env with intelligent type casting for numeric strings:
// config/app.php return [ // Automatic type casting from .env strings: 'port' => typedEnv()->getInt('PORT'), // "8080" → int(8080) 'rate' => typedEnv()->getFloat('RATE'), // "2.5" → float(2.5) 'limit' => typedEnv()->getFloat('LIMIT'), // "1e3" → float(1000.0) 'debug' => typedEnv()->getBool('APP_DEBUG'), // "true" → bool(true) // With defaults (never throws): 'name' => typedEnv()->getStringOr('APP_NAME', 'Laravel'), 'timeout' => typedEnv()->getFloatOr('TIMEOUT', 30.0), ];
Casting Rules:
- Numeric strings →
intorfloatbased on format (handles scientific notation, leading zeros, whitespace, overflow) - Boolean strings (
"true","false") →bool(handled by Laravel'sEnv) - Null strings (
"null","(null)") →null(handled by Laravel'sEnv) - All other strings remain unchanged
typedEnvString() Helper - For String Values
Use this helper when you have environment variables that are semantically strings but may contain only digits (passwords, tokens, API keys):
// config/auth.php return [ // Problem: typedEnv() casts "123456" to int, getStringOr returns '' // 'password' => typedEnv()->getStringOr('API_PASSWORD', ''), // Solution: typedEnvString() keeps all values as strings 'password' => typedEnvString()->getStringOr('API_PASSWORD', ''), 'token' => typedEnvString()->getString('API_TOKEN'), ];
Casting Rules:
- All scalar values (string, int, float, bool) →
string - Booleans:
true→"1",false→""(PHP's native casting) - Null remains
null
TypedConfig Facade - Use Anywhere
Wraps Laravel's Config facade with strict typing, no casting:
use TypedRegistry\Laravel\Facades\TypedConfig; // In controllers, services, jobs, etc. $driver = TypedConfig::getString('database.default'); $port = TypedConfig::getInt('database.connections.mysql.port'); $options = TypedConfig::getStringMap('database.connections.mysql.options'); // With defaults: $perPage = TypedConfig::getIntOr('app.pagination.per_page', 15);
Or use the helper function:
$driver = typedConfig()->getString('database.default');
Full API
All three helpers (typedEnv(), typedEnvString(), and TypedConfig) expose the same 20 methods from TypedRegistry:
Primitive Getters
->getString('KEY'); // string - throws if missing/wrong type ->getInt('KEY'); // int ->getBool('KEY'); // bool ->getFloat('KEY'); // float
Nullable Variants
->getNullableString('KEY'); // string|null ->getNullableInt('KEY'); // int|null ->getNullableBool('KEY'); // bool|null ->getNullableFloat('KEY'); // float|null
With Defaults (Never Throws)
->getStringOr('KEY', 'default'); // Returns default if missing/wrong type ->getIntOr('KEY', 8080); ->getBoolOr('KEY', false); ->getFloatOr('KEY', 1.5);
Lists (Sequential Arrays)
->getStringList('KEY'); // list<string> ->getIntList('KEY'); // list<int> ->getBoolList('KEY'); // list<bool> ->getFloatList('KEY'); // list<float>
Maps (Associative Arrays with String Keys)
->getStringMap('KEY'); // array<string, string> ->getIntMap('KEY'); // array<string, int> ->getBoolMap('KEY'); // array<string, bool> ->getFloatMap('KEY'); // array<string, float>
Type Casting Behavior
EnvProvider - Intelligent Casting
The EnvProvider (used by typedEnv()) intelligently casts numeric environment variable strings:
// Integer casting (handles edge cases) "123" → int(123) "-456" → int(-456) "0" → int(0) "042" → int(42) // Leading zeros removed "-042" → int(-42) // Negative with leading zeros "+42" → int(42) // Leading plus removed " 042 " → int(42) // Whitespace trimmed // Integer overflow protection (values exceeding PHP_INT_MAX/MIN) "9223372036854775808" → float(9.223372036854776E+18) // Too large for int "-9223372036854775809" → float(-9.223372036854776E+18) // Too small for int // Float casting (decimal point or scientific notation) "3.14" → float(3.14) "0.0" → float(0.0) "1e3" → float(1000.0) // Scientific notation "2.5e-4" → float(0.00025) // Scientific with decimal "1E10" → float(10000000000.0) // Uppercase E "042.5" → float(42.5) // No casting "Laravel" → "Laravel" // Non-numeric "123abc" → "123abc" // Mixed alphanumeric "" → "" // Empty string // Laravel's Env handles these: "true" → bool(true) "false" → bool(false) "null" → null "(null)" → null
EnvStringProvider - Cast to String
The EnvStringProvider (used by typedEnvString()) casts all scalar values to strings:
// All values become strings "123456" → "123456" // Numeric string preserved "3.14" → "3.14" // Float string preserved "1e3" → "1e3" // Scientific notation preserved "042" → "042" // Leading zeros preserved "Laravel" → "Laravel" // Non-numeric unchanged // Laravel's Env converts these first, then we cast to string: "true" → "1" // bool(true) → string "false" → "" // bool(false) → string "null" → null // Stays null (not scalar)
ConfigProvider - No Casting
ConfigProvider performs zero type coercion. Values must be stored with the correct type:
// config/app.php return [ 'port' => 8080, // ✅ int - TypedConfig::getInt() works 'port_str' => '8080', // ❌ string - TypedConfig::getInt() throws ];
Error Handling
Strict Getters Throw on Type Mismatch
use TypedRegistry\RegistryTypeError; try { $port = TypedConfig::getInt('app.name'); // If 'app.name' is a string } catch (RegistryTypeError $e) { // "[typed-registry] key 'app.name' must be int, got 'Laravel'" }
Default Getters Never Throw
// Returns default value on missing key OR type mismatch $port = typedEnv()->getIntOr('NONEXISTENT_PORT', 8080); // 8080 $timeout = TypedConfig::getFloatOr('cache.timeout', 3.0); // 3.0
Real-World Example
// config/app.php return [ 'name' => typedEnv()->getStringOr('APP_NAME', 'Laravel'), 'env' => typedEnv()->getStringOr('APP_ENV', 'production'), 'debug' => typedEnv()->getBoolOr('APP_DEBUG', false), 'url' => typedEnv()->getStringOr('APP_URL', 'http://localhost'), 'timezone' => 'UTC', 'locale' => typedEnv()->getStringOr('APP_LOCALE', 'en'), 'providers' => [ // Service providers... ], ];
// app/Http/Controllers/DashboardController.php use TypedRegistry\Laravel\Facades\TypedConfig; class DashboardController extends Controller { public function index() { $appName = TypedConfig::getString('app.name'); $isDebug = TypedConfig::getBool('app.debug'); $locale = TypedConfig::getString('app.locale'); return view('dashboard', compact('appName', 'isDebug', 'locale')); } }
PHPStan Integration
The package works seamlessly with PHPStan at max level:
/** @var int $port */ $port = TypedConfig::getInt('app.port'); // PHPStan knows this is int /** @var list<string> $hosts */ $hosts = TypedConfig::getStringList('app.hosts'); // PHPStan knows the shape
Development
# Install dependencies composer install # Run tests composer test # or: vendor/bin/phpunit # Run static analysis composer phpstan # or: vendor/bin/phpstan analyse
Quality Standards:
- PHPStan Level: Max (10) with strict rules
- Test Coverage: All providers and facades
- PHP Version: 8.3+
- Laravel Version: 11+, 12+, 13+
Comparison with Core Package
| Feature | alexkart/typed-registry |
alexkart/typed-registry-laravel |
|---|---|---|
| Framework | Framework-agnostic | Laravel-specific |
| Type Casting | None (strict only) | EnvProvider casts numeric strings |
| String Preservation | N/A | EnvStringProvider keeps all as strings |
| Facades | No | TypedConfig |
| Helper Functions | No | typedEnv(), typedEnvString(), typedConfig() |
| Auto-discovery | N/A | Yes |
| Laravel Best Practices | N/A | Enforced (env only in config) |
Contributing
Contributions are welcome! Please ensure:
- All tests pass (
vendor/bin/phpunit) - PHPStan Level 10 passes (
vendor/bin/phpstan analyse) - Code follows existing style (strict types, final classes)
License
MIT License. See LICENSE for details.
Credits
- Built on alexkart/typed-registry
- Maintained by the TypedRegistry contributors
Questions? Open an issue on GitHub.
alexkart/typed-registry-laravel 适用场景与选型建议
alexkart/typed-registry-laravel 是一款 基于 PHP 开发的 Composer 扩展包,目前已累计 554 次下载、GitHub Stars 达 1, 最近一次更新时间为 2025 年 10 月 20 日, 在 PHP 生态内属于活跃度较高的组件。
它主要适用于以下技术方向: 「config」 「laravel」 「strict」 「env」 「static-analysis」 「PHPStan」 等业务场景。在实际项目中,围绕这些方向常见需要落地的问题包括:接口对接、性能调优、并发安全、与既有框架(Laravel / ThinkPHP / Yii / Webman 等)的兼容适配,以及生产环境的日志埋点与稳定性保障。
我们在过去多个企业项目中使用过 alexkart/typed-registry-laravel 或与其功能相近的方案,如果你在选型或落地过程中遇到问题,例如 版本兼容、二次改造、私有化封装、与内部系统对接、生产 BUG 排查,欢迎联系我们协助评估。
基于 alexkart/typed-registry-laravel 在你已有业务上做功能扩展、字段裁剪、UI 适配、与内部账号 / 权限 / 日志系统的深度对接。
线上偶发问题、内存泄漏、慢查询、并发异常等排查修复;针对高流量场景做缓存、队列、索引层面的调优。
承接完整的项目从需求 → 设计 → 开发 → 上线 → 长期运维;也可按月提供技术保姆服务。
与 alexkart/typed-registry-laravel 相关的其它包
同方向 / 同关键字的高下载量 PHP Composer 包推荐,方便对比选型:
Base object, checking access to undefined properties and methods
A Zend Framework module to quickly and easily set PHP settings.
Strict Typing for local variables in PHP
Package to improve Laravel framework with features to support more strict typed Laravel.
Free service to identify primitive type of a variable
Server environment detection based on config array-file
统计信息
- 总下载量: 554
- 月度下载量: 0
- 日度下载量: 0
- 收藏数: 1
- 点击次数: 3
- 依赖项目数: 0
- 推荐数: 0
其他信息
- 授权协议: MIT
- 更新时间: 2025-10-20