php 8.3 中不推荐用 rand()(已废弃并触发 e_deprecated)和 mt_rand()(虽未废弃但官方建议弃用),因其共享全局梅森旋转状态、无加密安全性,且易受干扰;应优先使用 random_int()(轻量安全整数)或 random\randomizer(面向对象、隔离、灵活)。

PHP 8.3 中不推荐用 rand(),也不该再手动调用 mt_rand();默认应优先使用 random_int() 或 Random\Randomizer 类。
为什么不能继续用 rand() 和 mt_rand()
PHP 8.3 已将 rand() 彻底标记为废弃(E_DEPRECATED),调用时会触发警告;mt_rand() 虽未废弃,但官方文档明确建议“所有新代码应改用 Random\Randomizer”。根本原因有三点:
-
rand()和mt_rand()共享全局梅森旋转状态,任意地方调用mt_srand()、srand()或array_rand()都会干扰其他随机逻辑,尤其在长生命周期的 Swoole 或 PHP-FPM 请求中极易出错 - 它们都不提供加密安全保证,哪怕只生成一个临时 token,也存在被预测风险
-
rand(1, 100)这类写法在 PHP 8.3 下仍能运行,但已失去维护支持,未来版本可能直接移除
random_int() 适合什么场景
这是最轻量、最安全的替代方案,底层直连操作系统 CSPRNG(/dev/urandom 或 BCrypt),无需实例化,开箱即用。适用于:
- 生成短信验证码:
random_int(100000, 999999) - 生成密码重置令牌:
bin2hex(random_bytes(16))(注意:这里用random_bytes(),不是random_int()) - 抽奖编号、订单号后缀等需防预测的整数
⚠️ 注意:random_int() 只返回整数,不能直接生成浮点数或字符串;若需小数,得自己做缩放(如 (random_int(0, 1000) / 1000.0)),但通常没必要——业务逻辑里很少真需要加密安全的随机浮点数。
Random\Randomizer 怎么初始化和使用
这是 PHP 8.2 引入、PHP 8.3 全面主推的面向对象方案,灵活性远超旧函数。关键点:
- 必须显式传入引擎,安全场景固定用
new Random\Engine\Secure() - 不依赖全局状态,每个
Randomizer实例完全隔离 - 支持更多分布类型:均匀整数、均匀浮点、加权数组抽样等
示例:安全地从用户列表随机选 3 个不重复 ID
$users = [101, 102, 103, 104, 105]; $randomizer = new Random\Randomizer(new Random\Engine\Secure()); $keys = $randomizer->pickArrayKeys($users, 3); // 返回类似 [2, 0, 4],对应 $users[2], $users[0], $users[4]
若只是取单个值,$randomizer->getInt(1, 100) 比 random_int(1, 100) 略重,但统一了 API 风格,便于后期扩展(比如切换非安全引擎做性能压测)。
容易忽略的兼容性细节
PHP 8.3 的变化不是“功能增强”,而是“边界收紧”:
-
array_rand($arr, 1)在 PHP 8.3 中仍可用,但它内部仍走全局 Mt19937,和Randomizer不互通,混用会导致不可控的序列偏移 -
getrandmax()函数还在,但已无实际意义——它返回的是历史遗留值,和当前Randomizer无关 - 如果你在 Composer 包里封装了随机工具类,请立刻检查是否硬编码了
mt_rand();PHP 8.3 下这类包在严格错误级别下会报E_DEPRECATED
真正麻烦的从来不是“怎么写新代码”,而是老项目里散落各处的 rand(1, 10) ——它们不会立刻崩,但会在某次升级后悄悄变成安全隐患或调试噩梦。
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











