Skip to content

Repository files navigation

Unit

Latest Stable VersionTotal DownloadsPushcodecovPHP VersionLicense

Type-safe units, quantities & dimensional analysis for PHP

A lightweight, immutable, type-safe PHP library for working with quantities, units, and dimensional analysis. Define units, convert across compatible ones, and do arithmetic that refuses to add meters to seconds.

useKhaledAlam\Unit\Quantity;
echo Quantity::of(2, 'm')->add(Quantity::of(100, 'cm'))->to('m'); // "3 m"echo Quantity::of(100, '°C')->to('°F')->format(1); // "212.0 °F"echo Quantity::of(4, 'm')->multiply(Quantity::of(3, 'm')); // "12 m²"

No setup, no registration — common units are ready the moment you install.

▶️Try the live demo — an interactive converter running in your browser.


Why Unit?

UnitHand-rolled * factorRaw floats
Blocks nonsensical math (m + s)
Auto-converts compatible units
Affine temperature scales (°C/°F/K)⚠️ easy to get wrong
Derived units (m/s, )
Immutable value objects
Zero dependencies

If you've ever shipped a bug because someone stored centimeters in a "meters" column, this library is for you.


Installation

composer require khaledalam/unit

Requires PHP 8.2+.


Quick start

<?phprequire__DIR__ . '/vendor/autoload.php';
useKhaledAlam\Unit\Quantity;
// Common units are auto-registered — just use them.$length1 = Quantity::of(2.0, 'm');
$length2 = Quantity::of(100.0, 'cm');
$sum = $length1->add($length2); // auto-converts cm -> mecho$sum->to('m'); // "3 m"

Features

  • ✅ Immutable value objects
  • ✅ Dimensionally-aware arithmetic (add, subtract, multiply, divide)
  • ✅ Automatic conversion between compatible units (e.g. cm → m)
  • Correct affine temperature conversion (°C ↔ °F ↔ K)
  • ✅ Derived/compound units rendered as m/s, , m·s
  • ✅ Scalar math (times, dividedBy, pow, sqrt, abs, negate)
  • ✅ Named dimensions (dimensionName()"velocity")
  • ✅ Comparisons (equals, isGreaterThan, isLessThan)
  • JsonSerializable output, Laravel cast & Doctrine type
  • ✅ Enum-powered unit naming and a custom unit registry
  • ✅ Zero runtime dependencies

Usage

Conversion

echo Quantity::of(2, 'm')->to('cm'); // "200 cm"echo Quantity::of(5, 'km')->to('m'); // "5000 m"echo Quantity::of(1, 'h')->to('s'); // "3600 s"

Arithmetic

$speed = Quantity::of(10, 'm')->divide(Quantity::of(2, 's')); // "5 m/s"$area = Quantity::of(2, 'm')->multiply(Quantity::of(3, 'm')); // "6 m²"

All operations return newQuantity objects with the proper dimension and unit.

Scalar math

echo Quantity::of(5, 'm')->times(3); // "15 m"echo Quantity::of(10, 'm')->dividedBy(4); // "2.5 m"echo Quantity::of(2, 'm')->pow(2); // "4 m²"echo Quantity::of(4, '')->sqrt(); // "2 m"echo Quantity::of(-3, 'm')->abs(); // "3 m"

Dimension names

Quantity::of(1, 'm/s')->dimensionName(); // "velocity"
Quantity::of(1, 'N')->dimensionName(); // "force"
Quantity::of(1, 'Pa')->dimensionName(); // "pressure"

Temperature (affine scales)

echo Quantity::of(100, '°C')->to('°F')->format(1); // "212.0 °F"echo Quantity::of(32, '°F')->to('°C')->format(1); // "0.0 °C"echo Quantity::of(25, '°C')->to('K')->format(2); // "298.15 K"

Parsing strings

echo Quantity::parse('100 km/h')->to('mph')->format(2); // "62.14 mph"echo Quantity::parse('-40 °C')->to('°F')->format(1); // "-40.0 °F"echo Quantity::parse('5 ft 3 in')->to('cm')->format(2); // "160.02 cm" (segments summed)

Humanize (auto-pick the best unit)

echo Quantity::of(1500, 'm')->humanize(); // "1.5 km"echo Quantity::of(2500000, 'B')->humanize(); // "2.5 MB"echo Quantity::of(5400, 's')->humanize(); // "1.5 h"

Comparison

Quantity::of(1, 'm')->isGreaterThan(Quantity::of(90, 'cm')); // true
Quantity::of(1, 'm')->equals(Quantity::of(100, 'cm')); // true

Precision & formatting

echo Quantity::of(1, 'm')->divide(Quantity::of(3, 's'))->format(2); // "0.33 m/s"

JSON

echojson_encode(Quantity::of(2, 'm')); // {"value":2,"unit":"m"}

Custom units

Register your own units against a dimension:

useKhaledAlam\Unit\{Unit, Name, Dimension, UnitRegistry};
UnitRegistry::register(newUnit('yard', 'yd', 0.9144, newDimension(['L' => 1])));
echo Quantity::of(1, 'yd')->to('m'); // "0.9144 m"

Incompatible operations throw

Quantity::of(5, 'kg')->add(Quantity::of(3, 's')); // InvalidArgumentException

Supported units

DimensionUnits
Lengthmm, cm, m, km, in, ft, yd, mi
Massmg, g, kg, t, lb, oz
Timems, s, min, h, d, wk
Areacm², , km², ft², ha, acre
VolumemL, L, , gal
Temperature°C, °F, K
Speedm/s, km/h, mph, kn
Databit, B, KB, MB, GB, TB, KiB, MiB, GiB, TiB
ForceN, kN
EnergyJ, kJ, cal, kcal, Wh, kWh
PowerW, kW, hp
PressurePa, kPa, bar, atm, psi
FrequencyHz, kHz, MHz, GHz
Anglerad, deg, grad, turn

Need more? Open an issue or register your own.


Laravel integration

The package ships a service provider (auto-discovered) and an Eloquent cast. Store a quantity in a single column and get a Quantity back on access:

useIlluminate\Database\Eloquent\Model;
useKhaledAlam\Unit\Laravel\AsQuantity;
class Parcel extends Model
{
protectedfunctioncasts(): array
{
return ['weight' => AsQuantity::class];
}
}
$parcel->weight = Quantity::of(2.5, 'kg'); // stored as "2.5 kg"$parcel->weight->to('g'); // 2500 g$parcel->weight = '5 ft 3 in'; // strings are parsed on the way in

Register app-specific units via config/unit.php:

return [
'units' => [
new \KhaledAlam\Unit\Unit('furlong', 'fur', 201.168, new \KhaledAlam\Unit\Dimension(['L' => 1])),
],
];

Requires illuminate/database (already present in any Laravel app).


Symfony / Doctrine integration

A Doctrine DBAL type persists a Quantity as a string column. Register it once, then map any column with it:

useDoctrine\DBAL\Types\Type;
useKhaledAlam\Unit\Doctrine\QuantityType;
Type::addType(QuantityType::NAME, QuantityType::class); // e.g. in a bundle boot / bootstrap
useDoctrine\ORM\MappingasORM;
#[ORM\Column(type: 'quantity', nullable: true)]
public ?Quantity $weight = null;

Strings assigned to the property are parsed on write, and the column hydrates back into a Quantity on read.

Requires doctrine/dbal ^4.


Examples

Runnable scripts live in examples/:

php examples/basic.php
php examples/temperature.php
php examples/parse-and-humanize.php
php examples/scalar-math.php
php examples/shipping.php
php examples/physics.php

Testing & quality

composer test# PHPUnit
composer analyse # PHPStan (level max)
composer cs # PHP-CS-Fixer (dry run)

The suite combines PHPUnit test classes with .phpt scenario tests and holds 100% line coverage, verified on PHP 8.2, 8.3, and 8.4 in CI (PHPStan level max, PSR-12).


Contributing

Contributions are welcome! Please read CONTRIBUTING.md and the Code of Conduct. Adding a unit is usually a three-line change.


License

MIT © Khaled Alam

About

A lightweight PHP library for working with physical quantities and unit conversions. Supports arithmetic operations, precision formatting, and dimensional analysis.

Topics

Resources

Code of conduct

Contributing

Security policy

Stars

5 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages