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

Bcmath Polyfill Laravel Package

nanasess/bcmath-polyfill

Pure-PHP polyfill for PHP's bcmath extension, providing bcadd, bcmul and the rest of the arbitrary-precision math functions when the native extension isn't installed. Drop-in compatibility for libraries and apps that rely on bcmath, with no server configuration changes needed.

View on GitHub
Deep Wiki
Context7

Technical Evaluation

Architecture fit — This is a compatibility shim, not a capability addition. It only earns a place in the architecture when there is a hard constraint against installing PHP extensions: locked-down shared hosting, distro-pinned base images you don't own, or a distributed Laravel package/plugin that runs on customer infrastructure you can't inspect. In any environment where the platform team controls the Dockerfile, docker-php-ext-install bcmath (or apt-get install php8.x-bcmath) is one line and strictly dominates this dependency. Classify it as an environmental escape hatch: permitted at the runtime edge, prohibited inside domain/payment code that must remain portable. It offers no framework integration value — no service provider, no config, no facades — so "fit" is purely a question of whether the deployment constraint is real.

Integration feasibility — Technically trivial. Composer install, one autoloaded functions file, matching signatures. The non-trivial part is that the integration point is autoload ordering, not an API call: once loaded, it declares bcadd, bcsub, bcmul, bcdiv, bcmod, bcpow, bcsqrt, bccomp, bcscale (plus PHP 8.4 additions) into the global namespace. That is action-at-a-distance — any package in the graph can silently start resolving to the polyfill. Feasibility is high; governance effort is what makes it expensive.

Technical risk

  • Supply chain / bus factor: 2 stars, 0 dependents, single maintainer, derived from phpseclib/bcmath_compat. It is effectively an unaudited fork of a widely used shim. Zero dependents means near-zero external scrutiny of the delta.
  • Metadata anomaly: latest release is dated 2026-09-15 — a future date relative to assessment. Verify tag provenance, signing, and that the Packagist entry isn't a stale/placeholder release before pinning.
  • Correctness concentration: the risk is not "does bcadd work" but rounding semantics. PHP 8.4 introduced bcround/bcfloor/bcceil with explicit rounding modes; bcdiv truncation behaviour, bcmod sign handling, negative-zero normalisation, and exception types (ValueError/DivisionByZeroError) are all places a pure-PHP emulation drifts from the C extension. A drift here is a money bug.
  • Coverage gaps: the description enumerates nine functions but omits bcpowmod and any PHP 8.4 object-oriented BcMath\Number surface. Confirm the actual exported symbol set against your consumers rather than trusting the README.
  • Performance: arbitrary-precision arithmetic in PHP userland is typically one to two orders of magnitude slower than the C extension. Irrelevant for a checkout total; potentially a timeout for a nightly repricing job over 500k line items.
  • Redeclaration hazard: if ext-bcmath is loaded in any environment where the polyfill also loads, you get a fatal Cannot redeclare or a guarded no-op depending on how the bootstrap is written. The failure is environment-dependent and won't reproduce locally.

Key questions

  1. In which concrete environments can we genuinely not install ext-bcmath, and what is the cost of changing that? (Usually: near zero.)
  2. Does the package require PHP ≥ 8.4, or does it run on our floor and merely provide 8.4 functions? This is a go/no-go.
  3. What exactly happens when ext-bcmath is present — guarded function_exists no-op, or fatal?
  4. Which transitive dependency does it pull (phpseclib/phpseclib 2.x vs 3.x)? 2.x would be an EOL liability in our SBOM.
  5. Are the PHP 8.4 rounding modes byte-for-byte conformant with upstream, and is there a published conformance suite?
  6. Does it export bcpowmod and the OO BcMath\Number API, or only the nine documented functions?
  7. Who is the maintainer, what's the release cadence, and what is our fork/vendor contingency?
  8. What does the licence chain look like (MIT here, phpseclib upstream MIT — confirm no inherited notice obligations)?

Integration Approach

Stack fit — Composer-native, zero Laravel coupling, no service provider to register, no config to publish. It is intentionally invisible, which is both its appeal and its hazard. The correct placement is a root-level require in the application's composer.json (or a dedicated runtime-fallback meta-package) so the platform team owns the decision — never let a feature library pull it in transitively.

Migration path

  1. Inventory first. Grep the codebase and composer.lock for bcadd|bcsub|bcmul|bcdiv|bcmod|bcpow|bcsqrt|bccomp|bcscale and for packages known to hard-depend on BCMath (moneyphp/money, legacy Magento-derived code, invoicing/tax libraries). Establish the blast radius before adding a global override.
  2. Default to the extension. Add ext-bcmath to require in composer.json and to every image you build. This makes the constraint explicit and fails fast at install time rather than drifting into a silent polyfill.
  3. Quarantine the polyfill. Where the extension is genuinely unavailable, load it only in that build profile — a separate composer install --no-dev variant, a fallback image tag, or a conditional bootstrap guarded by extension_loaded('bcmath').
  4. Wrap the call sites. Introduce a thin internal Decimal value object (or adopt brick/math, which is pure PHP and needs no bcmath at all) and route new code through it. This gives you a swap-out point and stops the polyfill's global functions becoming your de facto API.

Compatibility

  • Pin an exact version and commit the lockfile; there is no release-cadence signal to justify a caret range.
  • Verify the package's PHP floor against your CI matrix (8.2/8.3/8.4) and its phpseclib constraint against what's already resolved.
  • Check for collisions with existing polyfills (symfony/polyfill-*) and with any config.platform.php setting in composer.json, which can mask whether the extension is truly present during resolution.
  • Test on both profiles: extension present and absent. The extension-present path is the one that breaks in production.

Sequencing

  1. ADR documenting the constraint, the decision, and the exit criteria.
  2. Golden-vector conformance suite (rounding modes, negative values, division by zero, scale edge cases) run against native BCMath as the oracle.
  3. CI job on a bcmath-disabled image; assert no fatal redeclare and identical outputs.
  4. Benchmark the heaviest arithmetic path with and without the polyfill; set a regression budget.
  5. Canary the fallback profile in one non-critical service before any payment-adjacent rollout.

Operational Impact

Maintenance — You are tracking a 2-star, single-maintainer package that follows PHP's own release cadence. Expect to own patches: when PHP 8.5/8.6 ships new BCMath functions, this package is the only thing standing between you and a fatal "undefined function" in the fallback profile. Budget for a vendored fork or a Dependabot-with-human-review policy; do not enable auto-merge on this dependency.

Support — No vendor, no SLA, no issue-triage history to lean on. Internal support load falls entirely on the platform team, and the questions will be of the worst kind: "why did the totals differ between the staging and prod images?" Document the fallback profile explicitly in the runbook and tag the relevant images so on-call can see at a glance whether the polyfill is live.

Scaling — CPU-bound and single-threaded in userland. Horizontal scaling still works, but per-request cost rises on any hot arithmetic path, and batch jobs (invoicing runs, repricing, report generation) are where this bites. Keep the polyfill out of queue workers doing bulk financial recalculation, or move those workers to an image with the extension. Memory also grows faster for large operands; watch for elevated peak usage in long-running workers.

Failure modes (ranked by severity)

  1. Silent precision/rounding drift — polyfill and extension disagree on a rounding mode; totals differ by a cent; reconciliation breaks weeks later. Mitigation: conformance suite against native BCMath, plus a production assertion that all nodes in a given write path share the same arithmetic backend.
  2. Fatal redeclare — extension and polyfill both loaded via a config or base-image change; the app dies at boot, environment-specific. Mitigation: guard the bootstrap with extension_loaded(), and smoke-test both profiles in CI.
  3. Slow-path timeout — batch job crosses its timeout only in the fallback profile. Mitigation: benchmark gate in CI, queue-level alerts on job duration.
  4. Global namespace leakage — a new dependency starts relying on the polyfilled functions without anyone noticing; removing the polyfill later becomes a breaking change. Mitigation: internal Decimal abstraction and a locked dependency set.
  5. Abandonment — upstream goes quiet and a future PHP minor introduces an incompatible signature. Mitigation: vendored fork path documented in the ADR.

Ramp-up — Developer-facing effort is near zero: signatures match, so nobody has to learn an API. The cost is conceptual, not technical — engineers must internalise that a global function may be emulated, that behaviour can differ by deployment target, and that "it works locally" is not evidence here. A one-page ADR plus a lint rule or review checklist item ("no direct bc* calls outside the decimal adapter") is sufficient. Realistic estimate: half a day for the platform engineer who owns the ADR, CI matrix, and benchmark; a short team briefing thereafter. The genuine on-cost is the standing maintenance obligation on a package with 2 stars — that is the line item to weigh against the single docker-php-ext-install bcmath it replaces.

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.
socialdept/atp-orm
cboxdk/laravel-assistant-client
socialdept/atp-resolver
socialdept/tenant-domains
tautvydasr/blade-class-names
socialdept/color-scales
maherelgamil/controller
coleus/widgets
coleus/table
coleus/users
coleus/music
coleus/health
coleus/calendar
coleus/notes
coleus/support
coleus/settings
coleus/apps
seampact/laravel
emmyconceptng/laravel-ng-postcode
jjsquady/round-robin