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

Reference Money Laravel Package

baks-dev/reference-money

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Setup

  1. Installation:

    composer require baks-dev/reference-money
    

    Ensure your project uses PHP 8.4+ and Doctrine ORM (required dependency).

  2. Basic Usage:

    • Define a field in your Doctrine entity as ReferenceMoney type:
      use BaksDev\ReferenceMoney\Type\ReferenceMoneyType;
      
      #[ORM\Column(type: ReferenceMoneyType::NAME)]
      private string $amount;
      
    • Store/Retrieve values via the ReferenceMoney class:
      use BaksDev\ReferenceMoney\ReferenceMoney;
      
      $money = ReferenceMoney::fromFloat(123.45); // Stores as "12345" (string)
      $floatValue = $money->toFloat(); // Returns 123.45
      
  3. First Use Case:

    • Replace all decimal/float fields in financial entities (e.g., Order, Invoice) with ReferenceMoney to avoid floating-point precision issues.

Implementation Patterns

Core Workflows

  1. Entity Integration:

    • Use ReferenceMoneyType for Doctrine columns to auto-handle storage/retrieval.
    • Example entity:
      #[ORM\Entity]
      class Order {
          #[ORM\Column(type: ReferenceMoneyType::NAME)]
          private string $totalAmount;
      
          public function setTotal(float $amount): void {
              $this->totalAmount = ReferenceMoney::fromFloat($amount)->getValue();
          }
      
          public function getTotal(): float {
              return ReferenceMoney::fromString($this->totalAmount)->toFloat();
          }
      }
      
  2. API/Service Layer:

    • Convert between float and ReferenceMoney at service boundaries:
      class PaymentService {
          public function process(float $amount): void {
              $storedAmount = ReferenceMoney::fromFloat($amount);
              // Save to DB via repository...
          }
      }
      
  3. Validation:

    • Use ReferenceMoney::validate() to ensure values are valid before storage:
      if (!ReferenceMoney::validate($userInput)) {
          throw new \InvalidArgumentException("Invalid money format");
      }
      

Advanced Patterns

  • Custom Precision: Override the default 2-decimal precision by extending ReferenceMoney:

    class CustomMoney extends ReferenceMoney {
        public static function fromFloat(float $amount, int $precision = 4): self {
            return parent::fromFloat($amount * pow(10, $precision));
        }
    }
    
  • Query Filtering: Use ReferenceMoney in DQL for precise filtering:

    $query->andWhere('o.totalAmount = :amount')
          ->setParameter('amount', ReferenceMoney::fromFloat(100.0)->getValue());
    

Gotchas and Tips

Common Pitfalls

  1. Type Mismatch:

    • Error: ReferenceMoney::fromString() fails if the stored value isn’t a string.
    • Fix: Ensure Doctrine columns are typed as string (not integer or decimal).
      # config/doctrine/orm.yaml
      orm:
          mappings:
              App:
                  type: attribute
                  dir: "%kernel.project_dir%/src/Entity"
                  prefix: "App\Entity"
                  alias: App
                  is_bundle: false
                  # Ensure no custom type overrides exist
      
  2. Serialization Issues:

    • Error: JSON serialization fails if ReferenceMoney objects are directly serialized.
    • Fix: Convert to float/string before serialization:
      $serializable = $order->getTotal(); // Returns float
      
  3. Database Schema:

    • Gotcha: The package assumes the column is a string but doesn’t enforce it via migrations.
    • Tip: Add a custom migration or use Doctrine’s SchemaTool to validate:
      $schemaTool = new \Doctrine\ORM\Tools\SchemaTool($entityManager);
      $schemaTool->createSchema([new Order()]); // Validates column types
      

Debugging Tips

  • Verify Storage: Check raw DB values with:

    $money = ReferenceMoney::fromString("12345"); // Should return 123.45
    $storedValue = $money->getValue(); // Debug: "12345"
    
  • Precision Errors: If calculations seem off, inspect the stored value:

    $money = ReferenceMoney::fromString($entity->amount);
    $debug = $money->getValue() / 100; // Should match expected float
    

Extension Points

  1. Custom Storage: Override ReferenceMoney::getValue()/setValue() for non-string storage (e.g., integer):

    class IntegerMoney extends ReferenceMoney {
        public function getValue(): int {
            return (int) parent::getValue();
        }
    }
    
  2. Currency Support: Extend the class to include currency codes:

    class CurrencyMoney extends ReferenceMoney {
        private string $currency;
    
        public static function fromFloat(float $amount, string $currency): self {
            $instance = new self();
            $instance->setValue(ReferenceMoney::fromFloat($amount)->getValue());
            $instance->currency = $currency;
            return $instance;
        }
    }
    
  3. Event Listeners: Add validation listeners for prePersist/preUpdate:

    $entityManager->getEventManager()->addEventListener(
        \Doctrine\ORM\Events::prePersist,
        function ($event) {
            $entity = $event->getObject();
            if ($entity instanceof Order) {
                $entity->setTotal($entity->getTotal()); // Auto-convert
            }
        }
    );
    

Configuration Quirks

  • Doctrine Cache: Clear metadata cache if ReferenceMoneyType changes aren’t reflected:

    php bin/console doctrine:cache:clear-metadata
    
  • PHP Extensions: Ensure bcmath or gmp is installed for high-precision operations (though the package defaults to string math).

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.
terminal42/code-quality-tools
codifyo/ts-generator-bundle
andydefer/laravel-cluster
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
christhompsontldr/laravel-inky