Weave Code
Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Php Units Of Measure Laravel Package

triplepoint/php-units-of-measure

A PHP library for representing and converting units of measure. Work with physical quantities, perform arithmetic across compatible units, and add dimensional safety to applications that need reliable measurement calculations.

Deep Wiki
Context7

Getting Started

composer require triplepoint/php-units-of-measure

There is no service provider, config file, or facade — it is a plain Composer library, so it works identically in Laravel, plain PHP, or a queue worker.

The first practical use case is boundary conversion: accept a measurement from a user/API/import, convert it to a canonical unit immediately, and convert back to a display unit only when rendering.

use PhpUnitsOfMeasure\PhysicalQuantity\Length;

$package = new Length(12, 'in');

$package->toUnit('cm');     // 30.48
$package->toNativeUnit();   // 0.3048 (Length's native unit is the meter)

Where to look first:

  1. src/PhysicalQuantity/ — the authoritative list of supported quantities and, inside each class, the exact unit names and aliases. This is your cheat sheet; the README does not enumerate everything.
  2. src/PhysicalQuantity.php — the core API: toUnit(), toNativeUnit(), add(), subtract(), isEquivalentTo(), getUnit().
  3. src/UnitOfMeasure.php — conversion closures. Look here to understand why temperature behaves differently from length.
  4. tests/ — the best documentation of edge cases, aliases, and offset units.

Implementation Patterns

Convert at the edges, store consistently

Pick one storage convention (usually the quantity's native unit) and do all conversion at the application boundary. Do not persist a mixture of units in the same column.

final class MeasurementNormalizer
{
    public function lengthInMeters(float $value, string $unit): float
    {
        return (new Length($value, $unit))->toNativeUnit();
    }
}

Use value objects in domain code

Type-hint concrete quantity classes rather than passing float $value, string $unit pairs around. It makes illegal states harder to represent and keeps conversion logic in one place.

function shippingCost(Length $length, Mass $mass): Money
{
    // ...
}

Arithmetic

add() and subtract() operate in native units and mutate the receiver. Clone first if you want immutable semantics.

$total = new Length(1, 'm');
$total->add(new Length(50, 'cm'));       // 1.5 m
$total->subtract(new Length(2, 'in'));
echo $total->toUnit('cm');

Validate by constructing

The constructor throws for unknown units and non-numeric input, which makes it a natural validation primitive.

use PhpUnitsOfMeasure\Exception\UnknownUnitOfMeasure;

try {
    $length = new Length($request->input('value'), $request->input('unit'));
} catch (UnknownUnitOfMeasure $e) {
    abort(422, 'Unsupported unit.');
}

A Laravel validation rule can wrap the same try/catch:

public function passes($attribute, $value): bool
{
    try {
        new Length((float) ($value['value'] ?? 0), (string) ($value['unit'] ?? ''));
        return true;
    } catch (\Throwable) {
        return false;
    }
}

Eloquent cast / accessor

Store a native-unit float plus the original unit string (or just the native float if you never need to redisplay the original). Convert in an accessor/mutator. Keep the accessor's unit fixed so DB data is unambiguous.

API output

Never serialize the object directly. Emit an explicit shape:

return [
    'value' => round($length->toUnit('ft'), 3),
    'unit'  => 'ft',
];

Comparisons

Use isEquivalentTo() rather than == on converted floats.

$length->isEquivalentTo(new Length(100, 'cm')); // true

Custom units and quantities

Built-ins cover a wide range but not everything. The package supports registering UnitOfMeasure objects per quantity class, using to-native/from-native callables; a custom quantity means extending the base PhysicalQuantity and defining its unit table. The exact method name and UnitOfMeasure constructor have shifted between major versions, so mirror the pattern in the installed src/PhysicalQuantity/Length.php. Put all custom registrations in one bootstrap location (e.g. a service provider's register()), never scattered through the codebase.

Derived quantities

There is no dimensional-analysis engine: you cannot multiply Length by Length and get an Area. Compute derived values yourself in native units, then wrap them.

$speed = new Speed(
    (new Length(100, 'm'))->toNativeUnit()
        / (new Time(9.58, 's'))->toNativeUnit(),
    'm/s'
);

Gotchas and Tips

  • Everything is a float. Conversion is ordinary floating-point math; do not expect exact equality or arbitrary precision. Round at presentation time and use isEquivalentTo() or assertEqualsWithDelta() in tests.
  • Temperature is affine, not linear. Celsius/Fahrenheit/Kelvin conversions apply an offset, not just a scale. Temperature arithmetic is therefore semantically wrong for most use cases: 20°C + 10°C does not produce 30°C under the hood, because values are converted through Kelvin first. Model temperature differences separately; this library models point temperatures.
  • Absolute-zero behavior varies. Some versions guard against values below absolute zero via a package exception. Do not rely on it unless you have verified it in the installed version, and validate physical plausibility yourself.
  • Objects are mutable. add()/subtract() change the receiver. If you inject a quantity into multiple services, clone it or use immutable wrappers.
  • add() accepts any PhysicalQuantity. Type hints do not enforce that the argument is the same quantity class. Adding a Mass to a Length fails as an unknown unit or nonsense number, not a clean type error. Guard at API boundaries.
  • Unit aliases are per quantity and case-sensitive. C is Celsius in Temperature but could be coulomb in a charge quantity; m is meter in Length but minute in Time. Always pass the unit through the correct quantity class.
  • Native units are not uniform across quantities. Most are SI base units, but do not assume. Call toNativeUnit() and confirm before writing DB migrations or comparing values across systems.
  • Static unit registry. Units live in static state per class. That is fine for a standard registration bootstrap, but in long-running workers (Octane, queues) any conditional runtime registration persists across requests — a subtle source of cross-request bugs.
  • No formatting, locale, or significant figures. toUnit() returns a raw float. Formatting, thousands separators, and rounding are your responsibility.
  • Serialization is not built in. json_encode($length) will not produce a useful payload. Use getValue()/__toString() or map to explicit arrays.
  • Beware copy-pasted examples. The package has had API changes across major versions (UnitOfMeasure constructor, registration method names). Pin a version in composer.json and read the installed source rather than trusting blog snippets.
  • Assess maintenance risk. This is a small, low-activity package. It is MIT-licensed with a compact surface, so forking is realistic, but wrap it behind your own adapter/value objects so a replacement is a contained change.
  • Do not over-apply it. If you only ever store one unit, a float plus an enum is simpler. Reach for this library when units are genuinely dynamic — imports, multi-region catalogs, user-configurable display units, or scientific data.
Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
oxygen/data
oxygen/core
jengo/base
xiloryx/log-collector
a21ns1g4ts/filament-stripe
la-php/laravel-admin
artisan-build/community-prompts
vleroy/smart
ayles-software/laravel-australian-public-holidays
cboxdk/laravel-id-spatie
cboxdk/laravel-id-billing
cboxdk/laravel-id-billing-bridge
simple-as-fuck/php-performance-log
hsluv/hsluv
seampact/codegen
seampact/hooks
seampact/ir
mehedimi/laravel-amp-mail
happones/laravel-vue-i18n-generator
jwerd/inertia-table