使用SplQueue类实现PDO池

<?php
declare(strict_types=1);
ini_set('display_errors', 'On');
ini_set('error_reporting', E_ALL);

/**
 * PDO */
class PdoPool
{
    /**
     * @var int $size PDO池大小(即有多少个PDO对象)
     */
    private static int $size = 8;

    /**
     * @var SplQueue|null $splQueue 队列(即PDO池)
     */
    private static SplQueue|null $splQueue = null;

    /**
     * 获取PDO池当前PDO对象数量
     *
     * @return int PDO池当前PDO对象数量
     */
    public static function count(): int
    {
        if (static::$splQueue === null) {
            static::init();
        }

        return static::$splQueue->count();
    }

    /**
     * 从池中取出一个PDO对象
     *
     * @return PDO PDO对象
     */
    public static function get(): PDO
    {
        if (static::$splQueue === null) {
            static::init();
        }

        $pdo = static::$splQueue->dequeue();

        $hash = spl_object_hash($pdo);
        echo "从池中取出一个PDO对象($hash)" . PHP_EOL;

        return $pdo;
    }

    /**
     * 初始化PDO     *
     * @return void
     */
    private static function init(): void
    {
        static::$splQueue = new SplQueue();

        // 创建若干个PDO对象,并放入队列(即PDO池)
        for ($i = 0; $i < static::$size; ++$i) {
            static::$splQueue->enqueue(static::newPdo());
            echo '池当前PDO对象数量:' . static::$splQueue->count() . PHP_EOL;
        }
    }

    /**
     * 创建一个新的PDO对象
     *
     * @return PDO PDO对象
     */
    private static function newPdo(): PDO
    {
        $driver = 'mysql';
        $host = 'localhost';
        $dbname = 'test_db';
        $port = 3306;
        $charset = 'utf8mb4';
        $username = 'ZhangSan';
        $password = '********';

        $options = [
            PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
            PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,
            PDO::MYSQL_ATTR_INIT_COMMAND => "SET NAMES $charset",
            PDO::ATTR_EMULATE_PREPARES => false,
            PDO::ATTR_STRINGIFY_FETCHES => false,
        ];

        $dsn = "$driver:";
        $dsn .= "host=$host;";
        $dsn .= "dbname=$dbname;";
        $dsn .= "port=$port;";
        $dsn .= "charset=$charset;";

        return new PDO($dsn, $username, $password, $options);
    }

    /**
     * 将一个PDO对象放回池中
     *
     * @param PDO $pdo PDO对象
     * @return void
     */
    public static function put(PDO $pdo): void
    {
        if (static::$splQueue === null) {
            static::init();
        }

        $hash = spl_object_hash($pdo);
        echo "将一个PDO对象($hash)放回池中" . PHP_EOL;

        static::$splQueue->enqueue($pdo);
    }
}

$query = 'SELECT * FROM `prefix_user` WHERE `uid` = :uid LIMIT 1';
$params = ['uid' => 3];

$pdo = PdoPool::get(); // 从池中取出一个PDO对象
echo '(1)、池当前PDO对象数量:' . PdoPool::count() . PHP_EOL; // (1)、池当前PDO对象数量:7

$sth = $pdo->prepare($query);
$sth->execute($params);
$row = $sth->fetchAll()[0];
print_r($row);

PdoPool::put($pdo); // PDO对象放回池中
echo '(2)、池当前PDO对象数量:' . PdoPool::count() . PHP_EOL; // (2)、池当前PDO对象数量:8


//========== 说明 ==========//
// 1PDO对象使用完毕后应及时放回池中。

Copyright © 2025 码农人生. All Rights Reserved