spatie/weight-conversions
Lightweight PHP package for converting between common weight units (e.g., grams, kilograms, pounds, ounces). Handy for apps needing consistent unit handling in calculations, forms, and APIs, with a simple, dependency-free API.
The spatie/weight-conversions package is a lightweight utility for converting between different weight units (e.g., kilograms, pounds, grams, ounces). To begin, install it via Composer:
composer require spatie/weight-conversions
The package provides a simple facade (Weight) for conversions, eliminating the need for manual calculations. The first use case is straightforward: convert a weight value from one unit to another. For example:
use Spatie\WeightConversions\Facades\Weight;
// Convert 100 grams to kilograms
$kilograms = Weight::grams(100)->toKilograms(); // Returns 0.1
// Convert 5 pounds to kilograms
$kilograms = Weight::pounds(5)->toKilograms(); // Returns ~2.26796
Key starting points:
Weight::unit(value) to create a conversion object..toUnit() (e.g., toKilograms(), toPounds()) for conversions.Input Validation:
Ensure input values are numeric to avoid runtime errors. Use is_numeric() or Laravel’s floatval() for validation.
$weight = floatval(request('weight')); // Safely convert user input
$converted = Weight::kilograms($weight)->toPounds();
Dynamic Unit Handling:
Store unit types in a database (e.g., unit_type column) and dynamically call the conversion method using app() or a helper:
$unitType = $product->unit_type; // e.g., 'pounds'
$converted = Weight::{$unitType}($product->weight)->toKilograms();
Batch Conversions:
Process arrays of weights efficiently with array_map:
$weightsInGrams = [100, 200, 300];
$weightsInKg = array_map(
fn($g) => Weight::grams($g)->toKilograms(),
$weightsInGrams
);
API Responses: Normalize responses to a single unit (e.g., kilograms) for consistency:
return response()->json([
'weight' => Weight::pounds($product->weight)->toKilograms(),
'unit' => 'kg'
]);
Laravel Models: Add accessors to models for seamless conversions:
public function getWeightInKgAttribute()
{
return Weight::{$this->unit_type}($this->weight)->toKilograms();
}
Forms: Use the package to validate or transform input data in Form Requests:
public function rules()
{
return [
'weight' => 'required|numeric',
'unit' => 'required|in:grams,kilograms,pounds,ounces'
];
}
public function withValidator($validator)
{
$validator->after(function ($validator) {
$weight = Weight::{$this->unit}($this->weight)->toKilograms();
$validator->errors()->addIf(
$weight > 1000,
'weight',
'Weight cannot exceed 1000 kg.'
);
});
}
Localization: Combine with Laravel’s localization to display units in user-preferred formats (e.g., "kg" vs. "kilograms").
Precision Loss: Floating-point arithmetic can introduce rounding errors. For financial or critical applications, round results explicitly:
$rounded = round(Weight::ounces(10)->toKilograms(), 3); // 0.283
Unit Mismatches:
Ensure the input unit matches the method called (e.g., Weight::pounds() → .toKilograms()). Mixing units without conversion will yield incorrect results.
Negative Values: The package does not validate for negative weights. Handle edge cases in your application logic:
if ($weight < 0) {
throw new \InvalidArgumentException('Weight cannot be negative.');
}
Facade vs. Class:
While the facade (Weight) is convenient, avoid overusing it in performance-critical paths. Instantiate the class directly for micro-optimizations:
$converter = new \Spatie\WeightConversions\Weight();
$result = $converter->pounds(5)->toKilograms();
Unexpected Results:
Double-check the conversion direction (e.g., toKilograms() vs. toPounds()). Log intermediate values for debugging:
$pounds = Weight::kilograms(1)->toPounds();
\Log::debug("1 kg = {$pounds} lbs");
Unit Tests: Test edge cases (e.g., zero, maximum values, and rounding):
public function test_conversion_precision()
{
$this->assertEquals(0.453592, Weight::pounds(1)->toKilograms());
$this->assertEquals(0, Weight::grams(0)->toKilograms());
}
Custom Units:
Extend the package by creating a decorator or wrapper for non-standard units (e.g., metric tons). Override the convert() method in a custom class:
class CustomWeight extends \Spatie\WeightConversions\Weight
{
public function toMetricTons()
{
return $this->value / 1000;
}
}
Configuration: While the package lacks a config file, you can define constants or environment variables for default units:
config(['app.default_weight_unit' => 'kilograms']);
Laravel Service Provider: Bind the package to the container for dependency injection:
$this->app->bind(\Spatie\WeightConversions\Weight::class, function () {
return new \Spatie\WeightConversions\Weight();
});
Caching: Cache frequent conversions (e.g., static reference weights) if performance is critical:
$cacheKey = 'weight_conversion_' . md5($value . $fromUnit . $toUnit);
$converted = Cache::remember($cacheKey, now()->addHours(1), function () use ($value, $fromUnit, $toUnit) {
return Weight::{$fromUnit}($value)->{$toUnit}();
});
Batch Processing:
For large datasets, use Laravel’s collect() and map() for lazy evaluation:
$convertedWeights = collect($weights)->map(function ($weight) {
return Weight::grams($weight)->toKilograms();
});
How can I help you explore Laravel packages today?