Weave Code
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 Bundle Laravel Package

midnightluke/php-units-of-measure-bundle

Symfony bundle integrating the php-units-of-measure library, providing unit definitions and services to work with quantities, conversions, and formatting in your app. Adds simple configuration and DI wiring for unit-of-measure support.

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Setup

  1. Installation

    composer require midnightluke/php-units-of-measure-bundle
    

    Add to config/bundles.php:

    MidnightLuke\UnitsOfMeasureBundle\UnitsOfMeasureBundle::class => ['all' => true],
    
  2. First Use Case: Database Storage Define a Doctrine entity with a unit-aware field:

    use MidnightLuke\UnitsOfMeasureBundle\Doctrine\Types\UnitType;
    use MidnightLuke\UnitsOfMeasureBundle\Doctrine\Types\QuantityType;
    
    #[ORM\Entity]
    class Product {
        #[ORM\Column(type: QuantityType::NAME, options: ['unit' => 'kg'])]
        private Quantity $weight;
    }
    

    Run migrations (php bin/console doctrine:migrations:diff).

  3. Form Integration Use the UnitType and QuantityType in Symfony forms:

    $builder->add('weight', QuantityType::class, [
        'unit' => 'kg',
        'scale' => 2,
    ]);
    

Implementation Patterns

Workflow: Unit-Aware Calculations

  1. Define Units in Entities

    #[ORM\Column(type: QuantityType::NAME, options: ['unit' => 'm'])]
    private Quantity $length;
    
    • Supports predefined units (e.g., kg, m, s) or custom units via Unit::create().
  2. Form Handling

    • Automatically validates units and quantities.
    • Use UnitType for dropdowns of allowed units:
      $builder->add('unit', UnitType::class, [
          'units' => ['kg', 'g', 'mg'], // Restrict to specific units
      ]);
      
  3. Business Logic

    • Convert quantities between units:
      $quantity = new Quantity(10, 'kg');
      $grams = $quantity->convertTo('g'); // Returns 10000
      
    • Compare quantities (units must match):
      $weight1 = new Quantity(5, 'kg');
      $weight2 = new Quantity(5000, 'g');
      $weight1->equals($weight2); // true
      
  4. API/Serialization

    • Use JsonSerializable or custom serializers:
      $quantity->jsonSerialize(); // ["value" => 10, "unit" => "kg"]
      

Integration Tips

  • Doctrine Lifecycle Callbacks Validate units on prePersist/preUpdate:

    #[ORM\PrePersist]
    #[ORM\PreUpdate]
    public function validateUnits() {
        if (!$this->weight->getUnit()->isValid()) {
            throw new \InvalidArgumentException('Invalid unit');
        }
    }
    
  • Custom Units Extend the Unit class for domain-specific units (e.g., Unit::create('story_points')).

  • Symfony Validator Constraints Add custom validation:

    use MidnightLuke\UnitsOfMeasureBundle\Validator\Constraints\Unit;
    
    #[Assert\Unit(['units' => ['kg', 'g']])]
    private Quantity $weight;
    

Gotchas and Tips

Pitfalls

  1. Unit Mismatches

    • Comparing quantities with different units (e.g., 5 kg vs 5 m) throws UnitMismatchException.
    • Fix: Always convert to a common unit before comparison:
      $kgValue = $quantity->convertTo('kg')->getValue();
      
  2. Doctrine Type Configuration

    • Forgetting to specify unit in QuantityType defaults to Unit::NONE, which may not behave as expected.
    • Fix: Explicitly set the unit:
      #[ORM\Column(type: QuantityType::NAME, options: ['unit' => 'm'])]
      
  3. Form Data Binding

    • If the form submits {"value": "10", "unit": "kg"} but the entity expects m, binding fails.
    • Fix: Use UnitType with units option to restrict allowed units.
  4. Precision Loss

    • Floating-point arithmetic can cause unexpected results (e.g., 10 kg + 0.1 kg = 10.099999999999998 kg).
    • Fix: Use scale option in QuantityType:
      $builder->add('weight', QuantityType::class, ['scale' => 3]);
      

Debugging

  • Dumping Quantities Use var_dump($quantity->getValue()) and var_dump($quantity->getUnit()) for debugging.

    • For full details:
      var_dump($quantity->__toString()); // "10 kg"
      
  • Doctrine DBAL Exceptions If migrations fail, check:

    • The unit column exists in the database (Doctrine generates it automatically).
    • The value column is of type decimal (recommended for precision).

Extension Points

  1. Custom Unit Providers Override the default unit provider:

    // config/packages/midnight_luke_units_of_measure.yaml
    midnight_luke_units_of_measure:
        unit_provider: App\Service\CustomUnitProvider
    
  2. Quantity Listeners Add logic before/after quantity operations:

    use MidnightLuke\UnitsOfMeasureBundle\Event\QuantityEvent;
    
    $dispatcher->addListener(QuantityEvent::PRE_CONVERT, function (QuantityEvent $event) {
        if ($event->getQuantity()->getUnit() === 'm') {
            $event->setTargetUnit('cm'); // Force conversion to cm
        }
    });
    
  3. Custom Serialization Extend Quantity for JSON/API responses:

    class ApiQuantity extends Quantity implements JsonSerializable {
        public function jsonSerialize(): array {
            return [
                'value' => $this->getValue(),
                'unit' => $this->getUnit()->getSymbol(),
                'full_unit' => $this->getUnit()->__toString(),
            ];
        }
    }
    

Configuration Quirks

  • Default Unit The bundle does not enforce a default unit globally. Always specify units in:

    • Doctrine entity annotations (options: ['unit' => '...']).
    • Form types (unit option).
    • Manual Quantity instantiation (new Quantity(10, 'kg')).
  • Case Sensitivity Units are case-sensitive (e.g., kgKG). Use constants from Unit class for consistency:

    $quantity = new Quantity(10, Unit::KILOGRAM);
    
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.
besmartand-pro/php-quality-config
sentix/ai-chatbot
terminal42/code-quality-tools
codifyo/ts-generator-bundle
testo/fiber
mintobit/jobqueue
a4sex/maintenance-bundle
a4sex/entity-date-update
a4sex/client-identifier
a4sex/base-utilites
a4sex/key-value-storage
a4sex/micro-status
chilldev/dependency-injection-extra
datinglibre/datinglibre-app-api
biberltd/corebundle
bricre/symfony-bundle-test
biberltd/logbundle
dominium/http-adapter-bundle
dominium/google-analytics
a4sex/auto-clean-entity