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

Laravel Unit Laravel Package

jobmetric/laravel-unit

Laravel Unit is a package for working with measurement units in your Laravel app. It helps you define, manage, and convert units with a clean, extendable structure. Lightweight and easy to integrate, useful for storing and displaying quantities consistently.

View on GitHub
Deep Wiki
Context7

Getting Started

Install and publish. The package is jobmetric/laravel-unit, MIT, last released 2024-08-13 (1.2.0). Standard Laravel flow:

composer require jobmetric/laravel-unit
php artisan vendor:publish --tag=unit          # or --provider="JobMetric\Unit\UnitServiceProvider"
php artisan migrate

If your Laravel version's package discovery picks it up, you are done; older jobmetric releases expected the provider registered manually in config/app.php under providers. Confirm which applies by checking composer.json → extra.laravel.providers in vendor/jobmetric/laravel-unit.

Where to look first. The published config/unit.php is the whole mental model: it should carry the unit types (length, mass, volume, time…), their base unit, and each unit's factor or conversion definition. Read it before writing a line of code — the package's behaviour is config-driven, so the config is the documentation. Second: the migration (table shape, unique indexes, whether units are keyed by id or a stable code). Third: the service provider's bindings, which tell you what is container-resolved and therefore overridable.

First use case. Pick a single entity that carries a measurement — a product with weight, a shipment with volume, a recipe with quantity — store the canonical value plus its unit, and render it converted on display. That exercises the three things you will use daily: unit lookup, conversion, and formatting.

// persist canonically
$product->weight = 1250;          // grams
$product->weight_unit = 'g';

// present in whatever the user reads
$display = unit_convert($product->weight, 'g', 'lb'); // or Unit::convert(...)

Verify the actual entry point in src/ — jobmetric packages variously expose a helper (unit_convert(), unit()), a facade (Unit::convert()), or a service class bound in the container. Whichever it is, wrap it once in your own Measure value object so the rest of your app does not reach into the vendor API directly.

Implementation Patterns

Store canonical, convert at the edges. Keep one base unit per dimension in the database and convert only in form requests (input) and API resources / Blade (output). This kills the class of bug where three screens each store a differently-normalised number, and it means adding a new display unit is a config change, not a data migration.

Model the dimension, not just the unit. A unit only means something relative to its type. If the package exposes UnitType, use it; otherwise enforce it in your own layer — a length value must never silently convert into a mass unit. Validate unit.type == stored.type in the FormRequest and again in a domain guard, because the package will happily convert numerically if it only receives numeric input.

Define factors once, against the base. Pairwise conversion tables are N² and rot. If the config lets you declare each unit's factor to the type's base unit, do that and never add pairwise rules. If it does not, express pairwise helpers in terms of the base yourself.

Form handling. Accept { value, unit } pairs as input, validate the unit against an allow-list (Rule::in(array_keys(config('unit.units'))) or an exists against the published units table), then normalise in prepareForValidation() so validation rules see the canonical number.

API resources. Return both the canonical value and the display form, and be explicit about units — an unlabelled "weight": 1250 is a future incident.

return [
    'weight' => ['value' => $this->weight, 'unit' => $this->weight_unit, 'display' => unit_format($this->weight, $this->weight_unit)],
];

Formatting is a view concern. Put format() / abbreviation in an accessor, a Blade component, or a small presenter — never bake the string into the model and never persist the formatted string.

Seed or sync units from config. Treat config/unit.php as the source of truth and upsert into the units table on deploy, keyed on a stable code. Idempotent upsert(), not truncate-and-insert, so admin-added rows and foreign keys survive.

Translations. jobmetric packages lean on jobmetric/laravel-translation; unit labels and abbreviations are likely translatable. If so, resolve labels via __() and keep the symbol ('kg', '°C') as a non-translated column. Do not send translated unit names down an API consumed by another system.

Testing. Write a small Pest/PHPUnit helper that asserts round-trips (convert(convert($v, 'g', 'lb'), 'lb', 'g') ≈ $v) for every pair you actually support. Property-based-ish round-trip tests catch factor typos faster than eyeballing the config.

Gotchas and Tips

  • 1.2.0 is a dependency bump, not a feature release. The changelog only says it upgraded jobmetric/laravel-translation and the jobmetric core package. Treat the composer.lock diff as the real changelog: review changes to laravel/framework, php, and the core package before merging, and check whether the minimum Laravel/PHP version moved. composer why-not jobmetric/laravel-unit 1.2.0 will tell you what is blocking.
  • Clear the right caches after upgrading. php artisan config:clear && php artisan cache:clear, and restart queue workers — long-running processes hold the old container bindings and the old unit config.
  • Never call env() in config/unit.php. After config:cache it returns null. Put selection in config, read it via config().
  • Float precision. Conversion multiplies, and floats drift. Decide a precision policy up front: store integers in the smallest base unit where you can (grams, millimetres, cents-like), round only at the display boundary, and use round($v, $precision) from config rather than ad-hoc rounding scattered through views. For money-adjacent or regulatory values, use bcmath or brick/math in your own wrapper.
  • Persist a stable unit identifier, not a foreign key you might renumber. If the package keys units by auto-increment id, store the unit code ('kg') on your domain rows and resolve the id at write time. Renaming or re-seeding then cannot silently re-label historical rows.
  • Dimension mismatch silently converts. If a caller passes 'm' where 'kg' was expected and the package only receives numbers, you get a plausible-looking wrong answer. Guard in your own layer.
  • Unique index on code / (type, code). Without it, a re-run seeder or a race in an admin UI gives you duplicate units and non-deterministic lookups. Add the index in a follow-up migration if the published one lacks it.
  • Wide symbols and encodings. Unit symbols include °, µ, Ω. Use utf8mb4 on the units table and make sure your API serialises UTF-8, or those get mangled at the boundary.
  • N+1 on conversions. If conversion looks up the unit row per call, eager-load or memoise. A per-request in-memory map (units()->keyBy('code'), resolved once via a singleton or once()) is usually enough; do not hit the table per line item.
  • Bulk conversion belongs in SQL or in a chunked job, not in a Blade loop. For large tables, denormalise a canonical numeric column and convert only what you display.
  • Deleting or disabling a unit breaks history. Prefer soft deletes / a is_active flag over hard deletes, or stored values become un-resolvable when rendering old records.
  • Extension points. The service provider's bindings are the intended seam: bind your own converter or formatter implementation rather than forking. Laravel macros on the Unit model or facade are a cheap way to add app-specific helpers (Unit::forSelect()) without touching vendor code.
  • Thin docs, small package (6 stars). Plan for source-reading as primary support. Read src/, the config, and the migration before assuming behaviour; keep a thin adapter in your codebase so a future replacement is a one-file change.
  • Missing translation = the key in the UI. If labels render as unit.length.meter, that is a translation miss, not a conversion bug — check the driver/config for the translation package before debugging arithmetic.
  • Semver caution. A dependency bump shipped as 1.2.0 can still change effective behaviour via the upstreams. Run your round-trip conversion tests and a locale smoke test after every update; pin exact versions in production lockfiles and bump deliberately.
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.
mehedimi/laravel-amp-mail
happones/laravel-vue-i18n-generator
jwerd/inertia-table
siberfx/flysystem-wasabi
hollyit/token-replace
ippanelcom/laravel-sdk
adachsoft/changelog-linter
adachsoft/collection
payerurl/telegrambot-crypto-payment-instant-payout
dskripchenko/laravel-hybrid-search
riorizkyrainey/lara-ced
mehedimi/static-vel
zharp/zharp
nonsapiens/bigquery-model-sync
lgu-bayambang-ict-office/lgu-laravel-development-standards
andydefer/laravel-support
se7enxweb/flysystem
lampwick/laravel
jeslage/statamic-emojis
micahdshackelford/rmap-laravel