Installation
composer require windwalker/scalars ^4.0
Add to config/app.php under providers:
Windwalker\Scalars\ScalarsServiceProvider::class,
First Use Case
Convert a string to a scalar value (e.g., 123 → 123 as integer):
use Windwalker\Scalars\Facades\Scalar;
$value = Scalar::toInt('123'); // Returns 123 (int)
Key Classes
Scalar facade (primary entry point).Scalar::toInt(), Scalar::toFloat(), Scalar::toBool(), etc.Scalar::cast() for dynamic casting.Type Casting
// Convert to specific types
$int = Scalar::toInt('123abc', 0); // Returns 123 (ignores 'abc')
$float = Scalar::toFloat('3.14');
$bool = Scalar::toBool('true'); // Returns true (case-insensitive)
Dynamic Casting
$value = Scalar::cast('123', 'int'); // Equivalent to toInt()
$value = Scalar::cast(['foo' => 'bar'], 'array'); // Returns array
Validation + Casting
// Validate and cast in one step
$validInt = Scalar::toInt('123', null, ['min' => 0, 'max' => 100]);
// Returns 123 if valid, null otherwise
Laravel Integration
prepareForValidation():
public function prepareForValidation()
{
$this->merge([
'age' => Scalar::toInt($this->age, null, ['min' => 0]),
]);
}
protected $casts = [
'price' => [Scalar::class, 'toFloat'],
];
Batch Processing
$data = ['1', '2.5', 'false'];
$casted = array_map([Scalar::class, 'cast'], $data, array_fill(0, 3, 'float'));
// Returns [1.0, 2.5, 0.0]
Strict Validation
toInt('abc') returns null by default. Use a fallback:
Scalar::toInt('abc', 0); // Returns 0
['min' => 0]) throw exceptions on failure. Suppress with:
Scalar::toInt('abc', null, ['min' => 0], false); // Returns null
Boolean Quirks
Scalar::toBool('1') returns true (treats non-zero as true).'') return false, but '0' returns false (unlike PHP’s (bool)'0').Floating-Point Precision
toFloat('1.23456789') may lose precision. Use round() if needed:
Scalar::toFloat('1.234', null, null, 2); // Returns 1.23 (2 decimal places)
Array Handling
Scalar::cast($array, 'array') returns the same array. Use toArray() for deep casting:
Scalar::toArray(['foo' => '123'], ['foo' => 'int']); // ['foo' => 123]
Check Defaults
Scalar::getConfig() to inspect current settings (e.g., strict mode).config/scalars.php:
'strict' => false, // Allow loose casting
'fallback' => 0, // Global fallback value
Custom Validators
Scalar::extend():
Scalar::extend('even', function ($value) {
return $value % 2 === 0;
});
Scalar::toInt('123', null, ['even' => true]); // Returns null (fails)
Performance
$cache = [];
$casted = $cache[$key] ?? ($cache[$key] = Scalar::toInt($value));
Custom Types
Scalar::extend('uuid', function ($value) {
return Str::of($value)->startsWith('uuid:') ? Str::after($value, 'uuid:') : null;
});
Service Provider
register():
$this->app->bind('scalar.resolver.custom', function () {
return new CustomScalarResolver();
});
Facade Overrides
php artisan vendor:publish --provider="Windwalker\Scalars\ScalarsServiceProvider"
Scalar::cast() logic in app/Providers/AppServiceProvider.php:
Scalar::macro('customCast', function ($value) { ... });
How can I help you explore Laravel packages today?