php如何连接数据库代码怎么写
- 数据库
- 2025-08-17
- 8
以下是PHP连接数据库的完整技术指南,涵盖核心概念、多种实现方案、最佳实践及常见问题解决方案:
基础认知与前置条件
1 技术栈组成
| 组件 | 作用 | 典型版本 |
|---|---|---|
| PHP | 服务器端脚本语言 | >=7.4 |
| 数据库系统 | 数据存储管理平台 | MySQL/MariaDB/PostgreSQL/SQL Server等 |
| 数据库驱动 | PHP与数据库间的通信接口 | PDO/mysqli/pgsql等 |
| 网络协议 | 数据传输规范 | TCP/IP |
| SQL语句 | 数据库操作指令 | DDL/DML/DCL/TCL |
2 环境验证清单
LAMP/LNMP环境已搭建完成
PHP配置文件php.ini启用相关扩展:
; Windows系统取消注释以下行 extension=php_pdo_mysql.dll extension=php_mysqli.dll ; Linux系统执行命令: sudo apt install php-mysqlnd # 推荐高性能驱动
数据库服务正常运行且允许远程访问(默认端口3306)
创建测试数据库及用户账号(建议权限最小化原则)

三种主流连接方案详解
1 方案一:原生mysqli扩展(面向过程风格)
适用场景:简单项目快速开发,无需跨数据库兼容
<?php // 配置参数(实际开发应存入配置文件) define('DB_HOST', 'localhost'); define('DB_USER', 'username'); define('DB_PASS', 'password'); define('DB_NAME', 'database_name'); define('DB_CHARSET', 'utf8mb4'); // 支持emoji表情符号 // 建立持久连接(添加p:前缀) $conn = new mysqli(DB_HOST, DB_USER, DB_PASS, DB_NAME); if ($conn->connect_error) { die("连接失败: " . $conn->connect_error); } // 设置字符集(关键防中文乱码) $conn->set_charset(DB_CHARSET); // 执行查询示例 $sql = "SELECT FROM users WHERE id < ?"; $stmt = $conn->prepare($sql); // 使用预处理语句 $stmt->bind_param("i", $_GET['max_id']); // 绑定整型参数 $stmt->execute(); $result = $stmt->get_result(); // 遍历结果集 while ($row = $result->fetch_assoc()) { print_r($row); } // 关闭连接 $stmt->close(); $conn->close(); ?>
优势:执行效率高,内置专门优化过的MySQL协议层
劣势:仅支持MySQL系列数据库,API设计风格较旧
2 方案二:PDO接口(面向对象风格)
适用场景:多数据库兼容项目,企业级应用开发

try { // DSN格式:引擎名称://用户名:密码@主机地址:端口/数据库名?charset=编码 $dsn = 'mysql:host=localhost;dbname=test_db;charset=utf8mb4'; $options = [ PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION, // 开启异常模式 PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC, // 默认关联数组 PDO::ATTR_EMULATE_PREPARES => false, // 禁用模拟预处理 ]; $pdo = new PDO($dsn, 'db_user', 'secure_pass', $options); // 事务处理示例 $pdo->beginTransaction(); $stmt = $pdo->prepare("INSERT INTO products (name, price) VALUES (?, ?)"); $stmt->execute(['新产品', 99.99]); $stmt = $pdo->prepare("UPDATE inventory SET stock = stock 1 WHERE product_id = ?"); $stmt->execute([1]); $pdo->commit(); } catch (PDOException $e) { // 记录错误日志(生产环境不建议直接输出) error_log($e->getMessage()); http_response_code(500); echo "系统繁忙,请稍后再试"; }
关键特性对比表:
| 特性 | PDO | mysqli |
|——————–|————————-|————————-|
| 数据库兼容性 | ️ 支持12+种数据库 | 仅限MySQL系 |
| 参数绑定方式 | 命名占位符(?)+有序绑定 | 传统?占位符+类型声明 |
| 异常处理 | throw new PDOException | 返回布尔值+error属性 |
| 默认fetch模式 | 可通过选项配置 | 默认数值索引数组 |
| 预处理语句性能 | 相近 | 略优 |
| 事务支持 | 完整ACID事务 | 完整ACID事务 |
3 方案三:数据库连接池(高级优化)
适用场景:高并发Web应用,微服务架构

class DBPool { private static $instance; private $pool = []; const MAX_CONNECTIONS = 20; private function __construct() {} public static function getInstance(): self { if (!self::$instance) { self::$instance = new self(); } return self::$instance; } public function getConnection(): PDO { if (count($this->pool) < self::MAX_CONNECTIONS) { $dsn = 'mysql:host=db-cluster;dbname=app_db;charset=utf8mb4'; $pdo = new PDO($dsn, 'pool_user', 'pool_pass'); $pdo->setAttribute(PDO::ATTR_PERSISTENT, true); // 保持长连接 $this->pool[] = $pdo; return $pdo; } throw new Exception("达到最大连接数"); } public function release($pdo) { array_pop($this->pool); } } // 使用示例 $db = DBPool::getInstance()->getConnection(); $stmt = $db->prepare("SELECT FROM hot_data"); $stmt->execute(); DBPool::getInstance()->release($db);
性能指标对比:
| 指标 | 普通连接 | 连接池 | 提升幅度 |
|———————|—————|—————|———-|
| 首次请求耗时(ms) | 150-300 | 80-120 | ~40%↓ |
| 峰值QPS | 50-80 | 200-300 | 3-4倍 |
| 内存占用(MB) | 1.2/连接 | 0.8/复用 | -33% |
| 连接建立次数/分钟 | 120+ | 1-5 | >95%↓ |
安全加固措施
1 SQL载入防护矩阵
| 风险等级 | 防御策略 | 示例代码 |
|---|---|---|
| 高危 | 强制使用预处理语句 | $stmt->bind_param() |
| 中危 | 输入过滤+白名单校验 | filter_var($input, FILTER_VALIDATE_INT) |
| 低危 | ORM框架自动转义 | Laravel Eloquent模型 |
| 特殊场景 | Escaping机制 | $pdo->quote($string) |
2 凭证安全管理
️ 禁止硬编码敏感信息!推荐方案:
// 错误做法(绝对禁止!) $conn = new mysqli('localhost', 'root', '123456', 'mydb'); // 正确做法A:环境变量(Docker/K8s推荐) putenv('DB_PASSWORD=supersecret'); $pass = getenv('DB_PASSWORD'); // 正确做法B:配置文件(加入.gitignore) $config = parse_ini_file(__DIR__.'/../config/db.ini'); $conn = new PDO($config['dsn'], $config['user'], $config['pass']);
常见错误排查手册
| 错误代码/现象 | 可能原因 | 解决方案 |
|---|---|---|
| Connection refused | 防火墙拦截/数据库未启动/地址错误 | telnet 3306端口;检查my.cnf |
| Access denied | 用户名密码错误/权限不足 | FLUSH PRIVILEGES;GRANT授权 |
| Too many connections | 达到max_connections限制 | 调整ulimit;优化业务逻辑 |
| Chinese garbled | 字符集不匹配 | 统一使用utf8mb4 |
| Hydration failure | 返回类型与预期不符 | 显式指定fetch_mode |
| SSL connection required | 未启用SSL加密连接 | 配置CA证书;修改DSN添加ssl={…} |
相关问答FAQs
Q1: PDO和mysqli哪个性能更好?
A: 根据TechEmpower基准测试,在纯查询场景下mysqli比PDO快约5-8%,但在复杂事务处理时两者差距缩小至2%以内,建议选择标准如下:
- 单一MySQL项目 → 优先mysqli
- 多数据库兼容需求 → 强制使用PDO
- 团队熟悉程度 → 保持一致性更重要
- ORM框架集成 → 多数ORM底层使用PDO
Q2: 如何解决”The specified module could not be found”错误?
A: 这是典型的DLL加载失败问题,按以下顺序排查:
- 确认PHP版本与扩展模块位数一致(通过php -i查看Architecture项)
- Windows系统将php_pdo_mysql.dll复制到C:WindowsSystem32目录
- Linux系统执行ldd /path/to/php检查依赖库
- 重启Web服务器(Apache/Nginx)使配置生效
- 查看PHP错误日志(通常位于/var/log/php/error.log)
进阶学习路径
- 数据库设计:掌握范式理论,熟练使用Workbench建模工具
- 查询优化:学习EXPLAIN分析执行计划,合理添加索引
- 分布式架构:了解主从复制、读写分离、分库分表方案
- 监控告警:部署Prometheus+Grafana监控数据库性能指标
- 云数据库:体验AWS RDS、阿里云PolarDB等托管服务
通过本文提供的完整实施方案,开发者可以根据项目需求选择合适的连接方式,并遵循安全最佳实践构建稳定的数据库交互层,建议在实际项目中结合PSR规范,将数据库操作封装为独立的Service层,提升代码