spatie/workshop-unit-conversions
Lightweight PHP package for performing unit conversions in Laravel or any PHP app. Install via Composer and convert values between supported units with a simple API. Includes tests, changelog, and MIT license.
The spatie/workshop-unit-conversions package simplifies unit conversions in Laravel by providing a clean, fluent API for common measurements (e.g., length, weight, temperature, volume). Start by installing it via Composer:
composer require spatie/workshop-unit-conversions
The package is self-contained—no configuration is required. Begin with basic conversions like:
use Spatie\WorkshopUnitConversions\UnitConverter;
// Convert 10 kilometers to miles
$converter = new UnitConverter();
$result = $converter->convert('10 kilometers', 'miles'); // Returns ~6.21371
For Laravel-specific use, leverage dependency injection:
// In a controller/service
public function __construct(private UnitConverter $converter) {}
public function convertDistance(float $value, string $from, string $to): float
{
return $this->converter->convert("$value $from", $to);
}
First use case: Validate user-submitted measurements (e.g., product dimensions) by converting them to a standardized unit before storage.
Leverage the package’s method chaining for multi-step conversions:
$converter->convert('500 grams', 'pounds')
->round(2) // Optional: Round to 2 decimal places
->toString(); // Returns "1.10231 pounds"
Workflow:
trim(), strtolower()) before passing to convert().$cacheKey = "conversion_{$from}_{$to}_{$value}";
return Cache::remember($cacheKey, now()->addHours(1), fn() =>
$converter->convert("$value $from", $to)
);
Store converted values in a database while keeping original units for display:
// Migration
$table->string('dimension_value')->comment('Stored in meters');
$table->string('dimension_unit');
// Model
public function getDisplayDimensionAttribute(): string
{
return $this->converter->convert(
"{$this->dimension_value} meters",
$this->dimension_unit
)->toString();
}
Extend the package by adding custom units via a service provider:
// app/Providers/UnitConversionServiceProvider.php
public function register()
{
UnitConverter::addUnit('lightyears', 'astronomical_units', 63241.077);
}
Tip: Use this for domain-specific units (e.g., "pages" to "words" for publishing apps).
Validate and convert measurements in form requests:
public function rules()
{
return [
'weight' => 'required|string',
];
}
public function withValidator($validator)
{
$validator->after(function ($validator) {
$value = $this->weight;
$converted = UnitConverter::convert($value, 'kilograms');
$this->merge([
'weight_kg' => $converted->toString(),
]);
});
}
Case Sensitivity:
"kilometers" ≠ "Kilometers"). Use strtolower() on user input:
$converter->convert(strtolower($userInput), $targetUnit);
Unsupported Units:
UnitConverter::addUnit() or file an issue.Precision Loss:
round() or number_format():
$converter->convert('1 meter', 'feet')->round(4); // 3.28084
Laravel Cache Key Collisions:
"5'6"" for height). Normalize first:
Cache::remember("conversion_{$normalizedValue}_{$from}_{$to}", ...);
dd(UnitConverter::getRegistry());
UnitConverter::isValidUnit($input) to test if a unit is supported.Custom Conversion Logic:
Override the converter’s convert() method in a decorator:
class CustomUnitConverter extends UnitConverter
{
public function convert(string $value, string $to): self
{
// Add custom logic (e.g., log conversions)
return parent::convert($value, $to);
}
}
Localization: Translate unit names for UI display:
$units = [
'kilometers' => __('units.km'),
'miles' => __('units.miles'),
];
Testing: Mock the converter in tests:
$mock = Mockery::mock(UnitConverter::class);
$mock->shouldReceive('convert')
->with('10 kg', 'pounds')
->andReturn(new UnitConverter('22.0462'));
Avoid Re-instantiation: Store the UnitConverter as a singleton in a service container or app binding:
$app->singleton(UnitConverter::class, fn() => new UnitConverter());
Batch Conversions: For bulk operations (e.g., ETL), pre-load the registry:
$registry = UnitConverter::getRegistry();
// Process conversions manually for performance-critical paths
How can I help you explore Laravel packages today?