laminas/laminas-math
Laminas Math provides arbitrary-precision integer arithmetic via BCMath or GMP adapters and cryptographically secure random number and string generation. A lightweight PHP utility component for applications needing reliable math and randomness primitives.
composer require laminas/laminas-math
There is no Laravel auto-discovery, no service provider, no facade — it is a pure PSR-4 library. Install it, then call the static APIs directly or wrap them in your own helper.
Look here first:
src/Rand.php — Rand::getBytes(), Rand::getString(), Rand::getInteger(), Rand::getNumber(). This is the part 90% of people install the package for.src/BigInteger/BigInteger.php — the factory() entry point and the ADAPTER_GMP / ADAPTER_BCMATH / ADAPTER_PHP64 constants.src/BigInteger/Adapter/*.php — Gmp, Bcmath, Php64 (pure-PHP fallback). Read one adapter to see the exact numeric-string contract.src/Fibonacci.php — small demo utility, rarely production-relevant.First use case: generating a cryptographically secure token, or doing big-integer arithmetic (modular exponentiation, base conversion, ID obfuscation) on a host where you cannot assume an extension is present.
Reality check before you start: the package is archived (last release 2024-12-05, 25 stars). On any PHP 7+ / Laravel 8+ project, random_int() and random_bytes() make Rand redundant, and brick/math is a maintained replacement for BigInteger. Only reach for this package on legacy code you are already committed to.
Random tokens (the classic use). Rand is a thin wrapper over random_bytes:
use Laminas\Math\Rand;
$token = bin2hex(Rand::getBytes(32)); // 64 hex char token
$hex = Rand::getString(32, 'abcdef0123456789'); // chars from a charset
$id = Rand::getInteger(1000, 9999); // int in range
$big = Rand::getNumber(0, PHP_INT_MAX); // returns a *string*
Wrap it in a single service so you can swap the implementation later:
class TokenService
{
public function token(int $bytes = 32): string
{
return bin2hex(\random_bytes($bytes)); // prefer this; Rand is archived
}
}
Big integer math. The adapter is selected at construction time, not globally:
use Laminas\Math\BigInteger\BigInteger;
$bi = BigInteger::factory(); // auto-detect: GMP > BCMath > PHP64
$a = $bi->add('123456789012345678901', '987654321098765432109');
$m = $bi->powmod('4', '13', '497'); // modular exponentiation
$c = $bi->compare($a, $m); // -1 | 0 | 1
All operands and results are numeric strings — never trust them to be int-castable.
Pin the adapter explicitly on any production path where correctness or speed matters:
$bi = BigInteger::factory(BigInteger::ADAPTER_GMP); // fail fast if gmp absent
$bi = BigInteger::factory(BigInteger::ADAPTER_BCMATH); // arbitrary scale, slower
Base conversion / ID obfuscation is the one still-legitimate use: converting large integers to a custom alphabet without integer overflow. Combine div, mod, and compare in a small helper; do not use intval() anywhere in the loop.
Service container binding if you must inject it:
$this->app->singleton(\Laminas\Math\BigInteger\BigInteger::class, function () {
return \Laminas\Math\BigInteger\BigInteger::factory(\Laminas\Math\BigInteger\BigInteger::ADAPTER_GMP);
});
Lazy pattern for signed URLs / tokens: people reach for powmod to build RSA or HMAC-by-hand. Do not. Use hash_hmac() and Hash::make(). BigInteger is for arithmetic, not cryptography.
Rand is superseded by the language. Rand::getBytes()/getInteger() map 1:1 to random_bytes()/random_int() (PHP 7+). If you only need randomness, drop the dependency entirely.BigInteger::factory() with no argument falls back to Php64 if neither GMP nor BCMath is loaded. Everything still works — just painfully slow and 64-bit-PHP-only. Always pass the adapter constant and let it throw.compare(), add(), etc. return strings (or GMP objects depending on adapter internals). intval() on a result silently truncates. Cast only after you have checked magnitude with compare().getNumber() returns a string, getInteger() returns an int. They look interchangeable; they are not. The former supports ranges beyond PHP_INT_MAX, the latter does not.factory() call is independent — you cannot set a process-wide default. Centralize construction in a single factory method to avoid mixed adapters in one code path.$bi->getAdapterName() to confirm which backend you actually got. On CI images that lack GMP this is the fastest way to explain "why is it slow" or "why do results differ in the last digits".Php64 assumes 64-bit integers; on 32-bit PHP results are wrong, not just slow. Add composer check-platform-reqs to CI.Laminas\Math\BigInteger\Adapter\AdapterInterface to wrap brick/math (or ext-decimal). It is a small interface (add, sub, mul, div, mod, pow, powmod, sqrt, abs, compare, getAdapterName), and this is the cleanest migration path off the archived package.powmod makes RSA tutorials tempting. Use openssl_*, hash_hmac, Hash::make, Crypt::encryptString. BigInteger is not constant-time.Php64 and exercise your code without GMP installed on the test runner; assert on strings, not ints.Rand::getBytes($n) → random_bytes($n); Rand::getInteger($a,$b) → random_int($a,$b); BigInteger → brick/math (BigInteger, BigDecimal, BigNumber), which is maintained and has typed objects instead of numeric strings.How can I help you explore Laravel packages today?