Skip to content

MongoDB Int32 类型详解

本知识点承接《MongoDB数据类型概述》,后续延伸至《MongoDB数值计算》,建议学习顺序:MongoDB基础→数据类型概述→本知识点→数值计算

1. 概述

在MongoDB数据库中,Int32类型是一种BSON数值类型(BSON type 0x10),用于存储32位有符号整数。Int32类型的取值范围是-2,147,483,648到2,147,483,647(即-2^31到2^31-1),适合存储不需要更大范围的整数值。

在PHP中,我们使用MongoDB\BSON\Int32类来显式创建Int32类型的值。虽然PHP的整数类型会自动映射到适当的BSON数值类型,但在某些场景下需要显式指定Int32类型,例如确保数据类型一致性、与其他系统集成、或优化存储空间。

Int32类型的主要应用场景包括:存储计数器、状态码、小范围ID、枚举值、年龄等不需要大范围整数的场景。理解Int32类型有助于开发者更好地控制数值存储,优化数据库性能。

2. 基本概念

2.1 语法

MongoDB Int32类型在PHP中使用MongoDB\BSON\Int32类表示,其基本语法如下:

php
use MongoDB\BSON\Int32;

// 创建Int32对象
$int32 = new Int32(int $value);

// 参数说明:
// $value: 整数值,必须在-2147483648到2147483647范围内

Int32取值范围

边界说明
最小值-2,147,483,648-2^31
最大值2,147,483,6472^31-1
存储4字节32位有符号整数

MongoDB数值类型对比

类型BSON码范围存储
Int320x10±2.1×10^94字节
Int64/Long0x12±9.2×10^188字节
Double0x01±1.8×10^3088字节
Decimal1280x1334位精度16字节

2.2 语义

Int32类型在MongoDB中的语义主要体现在以下几个方面:

存储语义

  • 作为32位有符号整数存储
  • 类型码为0x10
  • 占用4字节存储空间

比较语义

  • 与其他数值类型进行数值比较
  • Int32与Int64、Double比较时按数值比较
  • 在排序中按数值大小排序

类型转换语义

  • PHP整数在范围内自动映射为Int32或Int64
  • 超出Int32范围自动提升为Int64
  • 显式Int32构造可强制类型
php
<?php
require_once __DIR__ . '/vendor/autoload.php';

use MongoDB\BSON\Int32;
use MongoDB\Client;

echo "=== Int32基本语义 ===\n\n";

// 1. 创建Int32对象
echo "1. 创建Int32对象:\n";
$int32 = new Int32(100);
echo "   类型: " . get_class($int32) . "\n";
echo "   值: " . $int32 . "\n";

// 2. JSON序列化
echo "\n2. JSON序列化:\n";
echo "   " . json_encode(['num' => $int32], JSON_PRETTY_PRINT) . "\n";

// 3. 取值范围
echo "\n3. 取值范围:\n";
echo "   最小值: " . new Int32(-2147483648) . "\n";
echo "   最大值: " . new Int32(2147483647) . "\n";

// 4. 类型比较
echo "\n4. 类型比较演示:\n";
$client = new Client('mongodb://localhost:27017');
$collection = $client->test->int32_demo;
$collection->drop();

$collection->insertMany([
    ['name' => 'Int32', 'value' => new Int32(100)],
    ['name' => 'PHP Int', 'value' => 100],
    ['name' => 'Double', 'value' => 100.0]
]);

$results = $collection->find(['value' => 100]);
echo "   查询 value = 100 的结果:\n";
foreach ($results as $doc) {
    echo "     - {$doc->name}\n";
}
?>

输出结果

=== Int32基本语义 ===

1. 创建Int32对象:
   类型: MongoDB\BSON\Int32
   值: 100

2. JSON序列化:
   {
       "num": {
           "$numberInt": "100"
       }
   }

3. 取值范围:
   最小值: -2147483648
   最大值: 2147483647

4. 类型比较演示:
   查询 value = 100 的结果:
     - Int32
     - PHP Int
     - Double

2.3 存储结构

Int32类型在BSON中的存储结构:

┌─────────────────────────────────────────────────────┐
│                  BSON Int32                         │
├─────────────────────────────────────────────────────┤
│  Type (1 byte): 0x10                                │
│  Name (cstring): 字段名                              │
│  Value (int32): 32位有符号整数                       │
│    └─ 4 bytes, little-endian                        │
└─────────────────────────────────────────────────────┘

3. 基础用法

3.1 创建Int32对象

php
<?php
require_once __DIR__ . '/vendor/autoload.php';

use MongoDB\BSON\Int32;

echo "=== 创建Int32对象 ===\n\n";

// 方式1:直接实例化
$int32_1 = new Int32(42);
echo "1. 直接实例化: " . $int32_1 . "\n";

// 方式2:从字符串创建
$int32_2 = new Int32("123");
echo "2. 从字符串创建: " . $int32_2 . "\n";

// 方式3:负数
$int32_3 = new Int32(-100);
echo "3. 负数: " . $int32_3 . "\n";

// 方式4:边界值
$int32_min = new Int32(-2147483648);
$int32_max = new Int32(2147483647);
echo "4. 边界值: min={$int32_min}, max={$int32_max}\n";

// 获取值
echo "\n获取值:\n";
echo "  __toString(): " . $int32_1->__toString() . "\n";
echo "  (int)转换: " . (int)$int32_1 . "\n";
?>

3.2 Int32与PHP整数的关系

php
<?php
require_once __DIR__ . '/vendor/autoload.php';

use MongoDB\BSON\Int32;
use MongoDB\Client;

echo "=== Int32与PHP整数的关系 ===\n\n";

$client = new Client('mongodb://localhost:27017');
$collection = $client->test->int_php;
$collection->drop();

// PHP整数自动映射
$collection->insertMany([
    ['name' => 'small_int', 'value' => 100],
    ['name' => 'large_int', 'value' => 3000000000],
    ['name' => 'explicit_int32', 'value' => new Int32(100)],
    ['name' => 'negative', 'value' => new Int32(-100)]
]);

echo "存储结果分析:\n";
$results = $collection->find([]);
foreach ($results as $doc) {
    $type = gettype($doc->value);
    $class = is_object($doc->value) ? get_class($doc->value) : 'native';
    echo "  {$doc->name}: {$doc->value} (PHP类型: {$type}, 类: {$class})\n";
}
?>

3.3 Int32在查询中的使用

php
<?php
require_once __DIR__ . '/vendor/autoload.php';

use MongoDB\BSON\Int32;
use MongoDB\Client;

echo "=== Int32在查询中的使用 ===\n\n";

$client = new Client('mongodb://localhost:27017');
$collection = $client->test->int32_query;
$collection->drop();

$collection->insertMany([
    ['name' => 'Item A', 'quantity' => new Int32(10)],
    ['name' => 'Item B', 'quantity' => new Int32(50)],
    ['name' => 'Item C', 'quantity' => new Int32(100)],
    ['name' => 'Item D', 'quantity' => new Int32(200)]
]);

// 精确查询
echo "精确查询 quantity = 50:\n";
$results = $collection->find(['quantity' => new Int32(50)]);
foreach ($results as $doc) {
    echo "  - {$doc->name}: {$doc->quantity}\n";
}

// 范围查询
echo "\n范围查询 quantity > 50:\n";
$results = $collection->find(['quantity' => ['$gt' => new Int32(50)]]);
foreach ($results as $doc) {
    echo "  - {$doc->name}: {$doc->quantity}\n";
}

// 排序
echo "\n排序查询(降序):\n";
$results = $collection->find([], ['sort' => ['quantity' => -1]]);
foreach ($results as $doc) {
    echo "  - {$doc->name}: {$doc->quantity}\n";
}
?>

4. 进阶用法

4.1 类型安全存储

php
<?php
require_once __DIR__ . '/vendor/autoload.php';

use MongoDB\BSON\Int32;
use MongoDB\Client;

echo "=== 类型安全存储 ===\n\n";

class Int32Storage
{
    private $collection;
    
    public function __construct($collection)
    {
        $this->collection = $collection;
    }
    
    public function insert(string $key, int $value): void
    {
        if ($value < -2147483648 || $value > 2147483647) {
            throw new InvalidArgumentException('Value out of Int32 range');
        }
        
        $this->collection->insertOne([
            'key' => $key,
            'value' => new Int32($value)
        ]);
    }
    
    public function increment(string $key, int $delta = 1): int
    {
        $result = $this->collection->findOneAndUpdate(
            ['key' => $key],
            ['$inc' => ['value' => new Int32($delta)]],
            ['returnDocument' => MongoDB\Operation\FindOneAndUpdate::RETURN_DOCUMENT_AFTER]
        );
        
        return (int)$result->value;
    }
    
    public function get(string $key): ?int
    {
        $result = $this->collection->findOne(['key' => $key]);
        return $result ? (int)$result->value : null;
    }
}

$client = new Client('mongodb://localhost:27017');
$collection = $client->test->int32_storage;
$collection->drop();

$storage = new Int32Storage($collection);

$storage->insert('counter', 0);
echo "初始值: " . $storage->get('counter') . "\n";

$storage->increment('counter', 5);
echo "增加5后: " . $storage->get('counter') . "\n";

$storage->increment('counter', 10);
echo "再增加10后: " . $storage->get('counter') . "\n";
?>

4.2 批量操作

php
<?php
require_once __DIR__ . '/vendor/autoload.php';

use MongoDB\BSON\Int32;
use MongoDB\Client;

echo "=== 批量操作 ===\n\n";

$client = new Client('mongodb://localhost:27017');
$collection = $client->test->int32_batch;
$collection->drop();

// 批量插入
$data = [];
for ($i = 1; $i <= 100; $i++) {
    $data[] = [
        'id' => new Int32($i),
        'value' => new Int32($i * 10)
    ];
}

$startTime = microtime(true);
$collection->insertMany($data);
$endTime = microtime(true);

echo "批量插入100条记录\n";
echo "耗时: " . round(($endTime - $startTime) * 1000, 2) . " ms\n";

// 批量更新
echo "\n批量更新:\n";
$startTime = microtime(true);
$collection->updateMany(
    ['id' => ['$lte' => new Int32(50)]],
    ['$set' => ['category' => 'A']]
);
$endTime = microtime(true);
echo "更新前50条记录\n";
echo "耗时: " . round(($endTime - $startTime) * 1000, 2) . " ms\n";

// 聚合统计
echo "\n聚合统计:\n";
$pipeline = [
    ['$group' => ['_id' => '$category', 'total' => ['$sum' => '$value'], 'count' => ['$sum' => 1]]]
];
$results = $collection->aggregate($pipeline);
foreach ($results as $result) {
    $category = $result->_id ?? 'null';
    echo "  分类 {$category}: 总和={$result->total}, 数量={$result->count}\n";
}
?>

4.3 与其他数值类型的转换

php
<?php
require_once __DIR__ . '/vendor/autoload.php';

use MongoDB\BSON\Int32;
use MongoDB\BSON\Int64;
use MongoDB\Client;

echo "=== 数值类型转换 ===\n\n";

$client = new Client('mongodb://localhost:27017');
$collection = $client->test->type_conversion;
$collection->drop();

// 存储不同数值类型
$collection->insertMany([
    ['name' => 'Int32', 'value' => new Int32(100)],
    ['name' => 'Int64', 'value' => new Int64(100)],
    ['name' => 'Double', 'value' => 100.5],
    ['name' => 'Native', 'value' => 100]
]);

echo "类型信息:\n";
$results = $collection->find([]);
foreach ($results as $doc) {
    $type = is_object($doc->value) ? get_class($doc->value) : gettype($doc->value);
    echo "  {$doc->name}: {$doc->value} ({$type})\n";
}

// 类型转换函数
echo "\n类型转换:\n";
function toInt32($value): Int32
{
    if ($value instanceof Int32) {
        return $value;
    }
    if ($value instanceof Int64) {
        $intVal = (int)(string)$value;
        return new Int32($intVal);
    }
    return new Int32((int)$value);
}

$values = [new Int64(500), 300.7, "200"];
foreach ($values as $v) {
    $int32 = toInt32($v);
    echo "  " . gettype($v) . " -> Int32: {$int32}\n";
}
?>

5. 实际应用场景

5.1 计数器系统

php
<?php
require_once __DIR__ . '/vendor/autoload.php';

use MongoDB\BSON\Int32;
use MongoDB\Client;

echo "=== 计数器系统 ===\n\n";

class Int32Counter
{
    private $collection;
    
    public function __construct($collection)
    {
        $this->collection = $collection;
    }
    
    public function init(string $name, int $initial = 0): void
    {
        $this->collection->insertOne([
            'name' => $name,
            'value' => new Int32($initial),
            'updated' => new MongoDB\BSON\UTCDateTime()
        ]);
    }
    
    public function increment(string $name, int $delta = 1): int
    {
        $result = $this->collection->findOneAndUpdate(
            ['name' => $name],
            [
                '$inc' => ['value' => new Int32($delta)],
                '$set' => ['updated' => new MongoDB\BSON\UTCDateTime()]
            ],
            [
                'returnDocument' => MongoDB\Operation\FindOneAndUpdate::RETURN_DOCUMENT_AFTER,
                'upsert' => true
            ]
        );
        
        return (int)$result->value;
    }
    
    public function get(string $name): int
    {
        $result = $this->collection->findOne(['name' => $name]);
        return $result ? (int)$result->value : 0;
    }
    
    public function reset(string $name): void
    {
        $this->collection->updateOne(
            ['name' => $name],
            ['$set' => ['value' => new Int32(0)]]
        );
    }
}

$client = new Client('mongodb://localhost:27017');
$collection = $client->test->int32_counters;
$collection->drop();

$counter = new Int32Counter($collection);

$counter->init('page_views');
echo "页面访问: " . $counter->increment('page_views') . "\n";
echo "页面访问: " . $counter->increment('page_views', 5) . "\n";
echo "当前值: " . $counter->get('page_views') . "\n";
?>

5.2 状态码存储

php
<?php
require_once __DIR__ . '/vendor/autoload.php';

use MongoDB\BSON\Int32;
use MongoDB\Client;

echo "=== 状态码存储 ===\n\n";

class StatusCodeManager
{
    private $collection;
    private $statusCodes = [
        0 => 'pending',
        1 => 'processing',
        2 => 'completed',
        3 => 'failed',
        4 => 'cancelled'
    ];
    
    public function __construct($collection)
    {
        $this->collection = $collection;
    }
    
    public function create(string $taskId, int $status = 0): void
    {
        $this->collection->insertOne([
            'task_id' => $taskId,
            'status' => new Int32($status),
            'status_name' => $this->statusCodes[$status],
            'created' => new MongoDB\BSON\UTCDateTime()
        ]);
    }
    
    public function updateStatus(string $taskId, int $status): void
    {
        $this->collection->updateOne(
            ['task_id' => $taskId],
            [
                '$set' => [
                    'status' => new Int32($status),
                    'status_name' => $this->statusCodes[$status]
                ]
            ]
        );
    }
    
    public function getByStatus(int $status): array
    {
        return $this->collection->find(['status' => new Int32($status)])->toArray();
    }
    
    public function getStatusName(int $code): string
    {
        return $this->statusCodes[$code] ?? 'unknown';
    }
}

$client = new Client('mongodb://localhost:27017');
$collection = $client->test->task_status;
$collection->drop();

$manager = new StatusCodeManager($collection);

$manager->create('task_1', 0);
$manager->create('task_2', 0);
$manager->create('task_3', 1);

echo "待处理任务:\n";
foreach ($manager->getByStatus(0) as $task) {
    echo "  - {$task->task_id}: {$task->status_name}\n";
}

$manager->updateStatus('task_1', 2);
echo "\ntask_1 更新为完成状态\n";
?>

5.3 库存管理

php
<?php
require_once __DIR__ . '/vendor/autoload.php';

use MongoDB\BSON\Int32;
use MongoDB\Client;

echo "=== 库存管理 ===\n\n";

class InventoryManager
{
    private $collection;
    
    public function __construct($collection)
    {
        $this->collection = $collection;
    }
    
    public function addProduct(string $sku, int $quantity): void
    {
        $this->collection->insertOne([
            'sku' => $sku,
            'quantity' => new Int32($quantity),
            'reserved' => new Int32(0),
            'updated' => new MongoDB\BSON\UTCDateTime()
        ]);
    }
    
    public function reserve(string $sku, int $amount): bool
    {
        $result = $this->collection->findOneAndUpdate(
            ['sku' => $sku, 'quantity' => ['$gte' => new Int32($amount)]],
            [
                '$inc' => [
                    'quantity' => new Int32(-$amount),
                    'reserved' => new Int32($amount)
                ]
            ],
            ['returnDocument' => MongoDB\Operation\FindOneAndUpdate::RETURN_DOCUMENT_AFTER]
        );
        
        return $result !== null;
    }
    
    public function release(string $sku, int $amount): void
    {
        $this->collection->updateOne(
            ['sku' => $sku],
            [
                '$inc' => [
                    'quantity' => new Int32($amount),
                    'reserved' => new Int32(-$amount)
                ]
            ]
        );
    }
    
    public function getInventory(): array
    {
        return $this->collection->find([])->toArray();
    }
}

$client = new Client('mongodb://localhost:27017');
$collection = $client->test->inventory;
$collection->drop();

$inventory = new InventoryManager($collection);

$inventory->addProduct('SKU001', 100);
$inventory->addProduct('SKU002', 50);

echo "初始库存:\n";
foreach ($inventory->getInventory() as $item) {
    echo "  {$item->sku}: 库存={$item->quantity}, 预留={$item->reserved}\n";
}

$inventory->reserve('SKU001', 20);
echo "\n预留20个SKU001后:\n";
foreach ($inventory->getInventory() as $item) {
    echo "  {$item->sku}: 库存={$item->quantity}, 预留={$item->reserved}\n";
}
?>

6. 性能优化

6.1 索引与Int32

php
<?php
require_once __DIR__ . '/vendor/autoload.php';

use MongoDB\BSON\Int32;
use MongoDB\Client;

echo "=== 索引与Int32 ===\n\n";

$client = new Client('mongodb://localhost:27017');
$collection = $client->test->int32_index;
$collection->drop();

// 创建索引
$collection->createIndex(['user_id' => 1]);
$collection->createIndex(['score' => -1]);

// 插入数据
$data = [];
for ($i = 1; $i <= 10000; $i++) {
    $data[] = [
        'user_id' => new Int32($i),
        'score' => new Int32(rand(0, 1000))
    ];
}
$collection->insertMany($data);

echo "插入10000条记录\n";

// 使用索引查询
echo "\n索引查询测试:\n";
$startTime = microtime(true);
$result = $collection->findOne(['user_id' => new Int32(5000)]);
$endTime = microtime(true);
echo "  查询user_id=5000: " . round(($endTime - $startTime) * 1000, 2) . " ms\n";

// 范围查询
$startTime = microtime(true);
$results = $collection->find(['score' => ['$gt' => new Int32(900)]])->toArray();
$endTime = microtime(true);
echo "  查询score>900: " . count($results) . " 条, " . round(($endTime - $startTime) * 1000, 2) . " ms\n";
?>

7. 安全注意事项

7.1 溢出检测

php
<?php
require_once __DIR__ . '/vendor/autoload.php';

use MongoDB\BSON\Int32;

echo "=== 溢出检测 ===\n\n";

class SafeInt32
{
    const MIN = -2147483648;
    const MAX = 2147483647;
    
    public static function create($value): Int32
    {
        $intValue = (int)$value;
        
        if ($intValue < self::MIN || $intValue > self::MAX) {
            throw new OverflowException("Value {$intValue} is out of Int32 range");
        }
        
        return new Int32($intValue);
    }
    
    public static function safeAdd(Int32 $a, Int32 $b): Int32
    {
        $result = (int)$a + (int)$b;
        return self::create($result);
    }
    
    public static function safeMultiply(Int32 $a, Int32 $b): Int32
    {
        $result = (int)$a * (int)$b;
        return self::create($result);
    }
}

// 测试
echo "安全创建:\n";
try {
    $int32 = SafeInt32::create(100);
    echo "  创建成功: {$int32}\n";
    
    $overflow = SafeInt32::create(3000000000);
} catch (OverflowException $e) {
    echo "  溢出错误: " . $e->getMessage() . "\n";
}

echo "\n安全运算:\n";
try {
    $a = new Int32(2000000000);
    $b = new Int32(2000000000);
    $sum = SafeInt32::safeAdd($a, $b);
} catch (OverflowException $e) {
    echo "  加法溢出: " . $e->getMessage() . "\n";
}
?>

8. 常见问题与解决方案

问题1:Int32和PHP整数有什么区别?

问题描述:PHP整数和MongoDB Int32有什么不同?

回答内容

PHP整数根据平台可能是32位或64位,而Int32固定为32位。

php
<?php
use MongoDB\BSON\Int32;

echo "=== Int32 vs PHP整数 ===\n\n";

echo "PHP整数大小: " . PHP_INT_SIZE . " 字节\n";
echo "PHP整数最大值: " . PHP_INT_MAX . "\n";

echo "\nInt32范围:\n";
echo "  最小值: -2147483648\n";
echo "  最大值: 2147483647\n";

echo "\n区别:\n";
echo "  1. Int32固定32位,PHP整数依赖平台\n";
echo "  2. Int32显式类型,PHP整数自动类型\n";
echo "  3. Int32存储更紧凑(4字节)\n";
?>

问题2:什么时候应该使用Int32?

问题描述:什么场景下应该显式使用Int32类型?

回答内容

当需要确保类型一致性、优化存储或与其他系统集成时使用Int32。

php
<?php
use MongoDB\BSON\Int32;

echo "=== Int32使用场景 ===\n\n";

echo "推荐使用Int32:\n";
echo "  1. 计数器、状态码等小范围整数\n";
echo "  2. 需要确保类型一致性的场景\n";
echo "  3. 与其他系统(如Java)集成\n";
echo "  4. 存储空间敏感的场景\n";

echo "\n示例:\n";
echo "  \$counter = new Int32(0);\n";
echo "  \$statusCode = new Int32(200);\n";
echo "  \$age = new Int32(25);\n";
?>

问题3:Int32溢出会怎样?

问题描述:超出Int32范围的值会发生什么?

回答内容

超出范围会抛出异常或自动转换为Int64。

php
<?php
use MongoDB\BSON\Int32;
use MongoDB\BSON\Int64;

echo "=== Int32溢出处理 ===\n\n";

// 正常范围
echo "正常范围:\n";
$normal = new Int32(2147483647);
echo "  最大值: {$normal}\n";

// 超出范围
echo "\n超出范围:\n";
try {
    $overflow = new Int32(2147483648);
} catch (InvalidArgumentException $e) {
    echo "  错误: " . $e->getMessage() . "\n";
}

echo "\n解决方案:\n";
echo "  1. 使用Int64存储大整数\n";
echo "  2. 使用Decimal128存储精确数值\n";
echo "  3. 在应用层进行范围检查\n";
?>

9. 实战练习

练习1:实现安全的计数器

练习描述:创建一个防溢出的计数器系统。

解题思路

  1. 检测溢出风险
  2. 提供安全操作方法
  3. 记录操作日志

参考代码

php
<?php
use MongoDB\BSON\Int32;
use MongoDB\Client;

class SafeCounter
{
    private $collection;
    
    public function __construct($collection)
    {
        $this->collection = $collection;
    }
    
    public function increment(string $name, int $delta = 1): int
    {
        $current = $this->get($name);
        $newValue = $current + $delta;
        
        if ($newValue > 2147483647) {
            throw new OverflowException('Counter would overflow');
        }
        
        $result = $this->collection->findOneAndUpdate(
            ['name' => $name],
            ['$set' => ['value' => new Int32($newValue)]],
            ['upsert' => true, 'returnDocument' => MongoDB\Operation\FindOneAndUpdate::RETURN_DOCUMENT_AFTER]
        );
        
        return (int)$result->value;
    }
    
    public function get(string $name): int
    {
        $result = $this->collection->findOne(['name' => $name]);
        return $result ? (int)$result->value : 0;
    }
}

echo "=== 安全计数器 ===\n\n";

$client = new Client('mongodb://localhost:27017');
$collection = $client->test->safe_counter;
$collection->drop();

$counter = new SafeCounter($collection);
echo "计数: " . $counter->increment('test') . "\n";
echo "计数: " . $counter->increment('test', 10) . "\n";
?>

练习2:实现状态机

练习描述:使用Int32实现状态机。

解题思路

  1. 定义状态常量
  2. 实现状态转换
  3. 验证转换合法性

参考代码

php
<?php
use MongoDB\BSON\Int32;
use MongoDB\Client;

class StateMachine
{
    private $collection;
    private $transitions = [
        0 => [1, 4],  // pending -> processing, cancelled
        1 => [2, 3],  // processing -> completed, failed
        2 => [],      // completed (terminal)
        3 => [0],     // failed -> pending (retry)
        4 => []       // cancelled (terminal)
    ];
    
    public function __construct($collection)
    {
        $this->collection = $collection;
    }
    
    public function create(string $id): void
    {
        $this->collection->insertOne([
            '_id' => $id,
            'state' => new Int32(0)
        ]);
    }
    
    public function transition(string $id, int $newState): bool
    {
        $doc = $this->collection->findOne(['_id' => $id]);
        if (!$doc) return false;
        
        $currentState = (int)$doc->state;
        if (!in_array($newState, $this->transitions[$currentState] ?? [])) {
            return false;
        }
        
        $this->collection->updateOne(
            ['_id' => $id],
            ['$set' => ['state' => new Int32($newState)]]
        );
        
        return true;
    }
    
    public function getState(string $id): int
    {
        $doc = $this->collection->findOne(['_id' => $id]);
        return $doc ? (int)$doc->state : -1;
    }
}

echo "=== 状态机 ===\n\n";

$client = new Client('mongodb://localhost:27017');
$collection = $client->test->state_machine;
$collection->drop();

$sm = new StateMachine($collection);
$sm->create('task_1');

echo "初始状态: " . $sm->getState('task_1') . "\n";
$sm->transition('task_1', 1);
echo "处理后状态: " . $sm->getState('task_1') . "\n";
$sm->transition('task_1', 2);
echo "完成后状态: " . $sm->getState('task_1') . "\n";
?>

10. 知识点总结

核心概念回顾

概念说明重要程度
BSON类型码0x10,32位有符号整数⭐⭐⭐
PHP类MongoDB\BSON\Int32⭐⭐⭐
取值范围-2^31 到 2^31-1⭐⭐⭐
存储空间4字节⭐⭐
比较语义数值比较⭐⭐
溢出处理抛出异常⭐⭐⭐

关键技能掌握

必须掌握

  1. Int32对象的创建
  2. 理解取值范围
  3. 溢出检测和处理
  4. 与PHP整数的区别

建议掌握

  1. 类型安全存储
  2. 计数器实现
  3. 状态码管理
  4. 性能优化

最佳实践清单

创建Int32

php
$int32 = new Int32(100);

安全操作

php
if ($value >= -2147483648 && $value <= 2147483647) {
    $int32 = new Int32($value);
}

计数器

php
$collection->updateOne(['name' => 'counter'], ['$inc' => ['value' => new Int32(1)]]);

常见错误避免

错误正确做法
忽略溢出添加范围检查
混用类型保持类型一致
过度使用根据需求选择类型

11. 拓展参考资料

官方文档

PHP驱动文档

相关章节