frost/distance
PHP distance conversion library for US and metric units. Convert between mi, ft, in, km, m, cm, and mm (US↔metric, US↔US, metric↔metric). Simple fluent API: setUnit(), setDistance(), convertTo().
Installation:
composer require frost/distance
Add to composer.json if not using autoloading:
"autoload": {
"psr-4": {
"App\\": "app/",
"Frost\\": "vendor/frost/distance/src/"
}
}
Run composer dump-autoload.
First Use Case: Convert a distance in kilometers to miles in a Laravel controller:
use Frost\Distance;
$converter = new Distance();
$miles = $converter->setUnit('km')->setDistance(10)->convertTo('mi');
return response()->json(['distance' => $miles]);
Key Files:
vendor/frost/distance/src/Distance.php (Main class)vendor/frost/distance/src/Unit.php (Unit definitions)Chaining for Readability:
$distance = (new Distance())
->setUnit('m')
->setDistance(1000)
->convertTo('ft');
Service Provider (Recommended for Reusability):
Register in config/app.php:
'providers' => [
// ...
Frost\DistanceServiceProvider::class,
],
Bind in DistanceServiceProvider.php:
public function register()
{
$this->app->singleton(Distance::class, function ($app) {
return new Distance();
});
}
Use via dependency injection:
public function __construct(private Distance $distance) {}
Laravel Facade (Optional):
Extend the package to create a facade (e.g., DistanceFacade):
// app/Providers/DistanceServiceProvider.php
public function boot()
{
Distance::setFacadeApplication($this->app);
}
Use in views/controllers:
use Frost\Facades\Distance;
$feet = Distance::setUnit('km')->setDistance(5)->convertTo('ft');
Form Request Validation: Validate distance inputs in Laravel requests:
public function rules()
{
return [
'distance' => 'required|numeric|min:0',
'from_unit' => 'required|in:mi,ft,in,km,m,cm,mm',
'to_unit' => 'required|in:mi,ft,in,km,m,cm,mm',
];
}
Model Observers/Accessors: Add distance conversion to Eloquent models:
// app/Models/Product.php
public function getConvertedDistanceAttribute()
{
return (new Distance())
->setUnit($this->unit)
->setDistance($this->distance)
->convertTo('km'); // Default to metric
}
Floating-Point Precision:
mm to mi may yield unexpected decimal results (e.g., 1609344 mm = 1.0000000000000002 mi).$miles = round($distance->convertTo('mi'), 6);
Unit Case Sensitivity:
'km', not 'KM').$unit = strtolower($request->input('unit'));
Unsupported Units:
mi, ft, in, km, m, cm, mm are supported. Custom units (e.g., nautical miles) will throw errors.Unit class or validate inputs:
$validUnits = ['mi', 'ft', 'in', 'km', 'm', 'cm', 'mm'];
if (!in_array($unit, $validUnits)) {
throw new \InvalidArgumentException("Unit {$unit} not supported.");
}
Zero Division Edge Cases:
0 to any unit works, but dividing by zero in intermediate steps (e.g., cm to mi) could theoretically occur if the library logic changes.if ($distance->setDistance(-1)->convertTo('mi')) {
throw new \InvalidArgumentException("Distance cannot be negative.");
}
Log Conversion Steps: Add debug output to trace conversions:
$distance->setUnit('cm')->setDistance(150000);
$miles = $distance->convertTo('mi');
\Log::debug("Conversion: {$distance->getDistance()} {$distance->getUnit()} = {$miles} mi");
Unit Tests: Write tests for critical conversions:
// tests/Unit/DistanceTest.php
public function testKmToMiles()
{
$this->assertEquals(0.621371, (new Distance())
->setUnit('km')->setDistance(1)->convertTo('mi'), null, 0.000001);
}
Add Custom Units:
Extend the Unit class to support additional units (e.g., nautical miles):
// app/Extensions/CustomUnit.php
namespace App\Extensions;
use Frost\Unit;
class CustomUnit extends Unit
{
public static function getNauticalMilesToMeters()
{
return 1852;
}
}
Register in a service provider:
Unit::addUnit('nm', 'nautical miles', CustomUnit::class);
Caching Conversions: Cache frequent conversions (e.g., API responses) using Laravel's cache:
$cacheKey = "distance_{$from}_{$to}_{$distance}";
$converted = \Cache::remember($cacheKey, now()->addHours(1), function () use ($distance, $from, $to) {
return $distance->setUnit($from)->setDistance($distance)->convertTo($to);
});
Laravel Scout Integration: Use distance conversions for geospatial search (e.g., "find locations within 10 km"):
$user = User::where('latitude', '<=', $currentLat + 10)
->where('latitude', '>=', $currentLat - 10)
->where('longitude', '<=', $currentLon + (10 / 69)) // Approx. conversion
->where('longitude', '>=', $currentLon - (10 / 69))
->first();
Replace with precise conversions using the library for accuracy.
API Resource Formatting: Format distance responses in API resources:
// app/Http/Resources/DistanceResource.php
public function toArray($request)
{
return [
'value' => $this->distance,
'unit' => $this->unit,
'converted' => [
'miles' => (new Distance())
->setUnit($this->unit)
->setDistance($this->distance)
->convertTo('mi'),
'kilometers' => (new Distance())
->setUnit($this->unit)
->setDistance($this->distance)
->convertTo('km'),
],
];
}
How can I help you explore Laravel packages today?