0

0

PHP mysqli 连接:面向对象与过程式风格解析与优化实践

心靈之曲

心靈之曲

发布时间:2025-11-05 12:21:30

|

1005人浏览过

|

来源于php中文网

原创

PHP mysqli 连接:面向对象与过程式风格解析与优化实践

本文深入探讨 php `mysqli` 扩展中面向对象与过程式两种风格的用法与转换。我们将对比二者差异,纠正常见错误,并提供从面向对象到过程式风格的转换示例。文章强调在现代 php 开发中,应优先选择面向对象风格或 pdo,并展示如何通过启用错误报告和简化结果获取来编写更简洁、健壮的数据库交互代码。

在 PHP 数据库交互中,mysqli 扩展提供了两种主要的操作风格:面向对象(Object-Oriented, OO)和过程式(Procedural)。理解这两种风格的差异及其适用场景,对于编写高效且可维护的数据库代码至关重要。

mysqli 的面向对象与过程式风格

mysqli 扩展最初设计时,面向对象风格是其推荐的使用方式,而过程式风格主要是为了帮助那些从旧版 PHP(如 PHP 4 的 mysql 扩展)迁移的用户平滑过渡。因此,在新的项目或代码中,强烈建议采用面向对象风格。

两者核心差异在于函数调用方式和参数传递:

  • 面向对象风格:通过 mysqli 类的实例调用方法,例如 $mysqli->prepare()。
  • 过程式风格:通过全局函数调用,并将 mysqli 实例作为第一个参数传入,例如 mysqli_prepare($mysqli, ...)。

值得注意的是,使用 mysqli 的面向对象风格并不意味着您的整个应用程序就必须是面向对象的。它仅仅是一种更现代、更清晰的 API 使用方式。

立即学习PHP免费学习笔记(深入)”;

常见的错误尝试与原因分析

用户在尝试将面向对象风格的代码转换为过程式时,常会遇到以下错误:

$connection = mysqli_connect('localhost', 'root', '', 'ems');
$query = "SELECT * FROM bookings WHERE MONTH(event_date) = ? AND YEAR(event_date)=?";
$get_dates = mysqli_query($connection, $query); // 错误的使用方式
while($row = mysqli_fetch_assoc($get_dates)){
    $booked_dates[] = $row['event_date'];
}

这段代码会抛出 Fatal error: Uncaught TypeError: mysqli_fetch_assoc(): Argument #1 ($result) must be of type mysqli_result 错误。

错误原因: 问题在于 mysqli_query() 函数的使用。mysqli_query() 适用于执行不带参数的简单查询,或者在非预处理语句模式下获取结果。当使用带有占位符(?)的预处理语句时,您不能直接将其传递给 mysqli_query()。预处理语句需要经过 prepare、bind_param、execute 等一系列步骤才能正确执行和获取结果。mysqli_query() 在这种情况下会返回 false(表示查询失败,因为 SQL 语法不完整或不被支持),而不是 mysqli_result 对象,导致后续 mysqli_fetch_assoc() 接收到错误类型的参数。

面向对象 mysqli 代码转换为过程式风格

尽管不推荐,但了解如何将面向对象风格的代码转换为过程式风格,有助于理解 mysqli 的内部机制。以下是将原始面向对象代码转换为过程式风格的示例:

原始面向对象代码:

Vondy
Vondy

下一代AI应用平台,汇集了一流的工具/应用程序

下载
function build_calendar($month, $year){
    $mysqli = new mysqli('localhost', 'root', '', 'ems');
    $stmt = $mysqli->prepare("SELECT * FROM bookings WHERE MONTH(event_date) = ? AND YEAR(event_date)=?");
    $stmt->bind_param('ss', $month, $year);
    $bookings = array();
    if($stmt->execute()){
        $result = $stmt->get_result();
        if($result->num_rows>0){
            while($row = $result->fetch_assoc()){
                $bookings[] = $row['event_date'];
            }
            $stmt->close();
        }
    }
    // 返回 $bookings 数组
    return $bookings;
}

转换为过程式风格:

function build_calendar_procedural($month, $year)
{
    // 1. 建立数据库连接
    $mysqli = mysqli_connect('localhost', 'root', '', 'ems');
    if (mysqli_connect_errno()) {
        // 错误处理:连接失败
        error_log("Failed to connect to MySQL: " . mysqli_connect_error());
        return []; // 返回空数组或抛出异常
    }

    // 2. 准备预处理语句
    $stmt = mysqli_prepare($mysqli, "SELECT * FROM bookings WHERE MONTH(event_date) = ? AND YEAR(event_date)=?");
    if (!$stmt) {
        // 错误处理:语句准备失败
        error_log("Failed to prepare statement: " . mysqli_error($mysqli));
        mysqli_close($mysqli);
        return [];
    }

    // 3. 绑定参数
    mysqli_stmt_bind_param($stmt, 'ss', $month, $year);

    $bookings = array();
    // 4. 执行语句
    if (mysqli_stmt_execute($stmt)) {
        // 5. 获取结果集
        $result = mysqli_stmt_get_result($stmt);
        if ($result) { // 检查结果集是否成功获取
            // 6. 检查行数并遍历结果
            if (mysqli_num_rows($result) > 0) {
                while ($row = mysqli_fetch_assoc($result)) {
                    $bookings[] = $row['event_date'];
                }
            }
            mysqli_free_result($result); // 释放结果集内存
        } else {
            // 错误处理:获取结果集失败
            error_log("Failed to get result set: " . mysqli_stmt_error($stmt));
        }
    } else {
        // 错误处理:语句执行失败
        error_log("Failed to execute statement: " . mysqli_stmt_error($stmt));
    }

    // 7. 关闭语句和数据库连接
    mysqli_stmt_close($stmt);
    mysqli_close($mysqli);

    return $bookings;
}

可以看到,过程式风格的函数调用方式只是将面向对象方法名转换为以 mysqli_ 或 mysqli_stmt_ 开头的函数名,并将 mysqli 或 stmt 对象作为第一个参数传入。

推荐的现代 mysqli 实践与优化

为了编写更健壮、简洁且易于维护的数据库代码,建议遵循以下实践:

  1. 坚持使用面向对象风格 mysqli 或 PDO:

    • PDO (PHP Data Objects) 是更推荐的选择,因为它提供了一致的接口来连接多种数据库,并且通常具有更简洁的 API。
    • 如果必须使用 mysqli,请始终选择面向对象风格。
  2. 启用 mysqli 错误报告: 默认情况下,mysqli 错误可能不会直接抛出异常,而是返回 false 或 null,需要手动检查。通过启用错误报告,可以将 mysqli 错误转换为异常,从而简化错误处理。

    mysqli_report(MYSQLI_REPORT_ERROR | MYSQLI_REPORT_STRICT);
    // 之后,任何 mysqli 错误都会抛出 mysqli_sql_exception 异常
  3. 简化结果获取: 对于获取所有行,可以使用 fetch_all(MYSQLI_ASSOC) 一次性获取所有结果,而不是手动循环 while($row = $result->fetch_assoc())。

优化后的面向对象 mysqli 示例:

// 在应用程序初始化阶段设置错误报告,通常在连接数据库之前
mysqli_report(MYSQLI_REPORT_ERROR | MYSQLI_REPORT_STRICT);

// 数据库连接对象通常作为全局变量或通过依赖注入传递
// 确保只创建一次连接
$mysqli_connection = new mysqli('localhost', 'root', '', 'ems');

/**
 * 从数据库中获取指定月份和年份的预订日期。
 *
 * @param mysqli $mysqli 数据库连接对象。
 * @param string $month 月份(例如 '01' 到 '12')。
 * @param string $year 年份。
 * @return array 预订日期数组,例如 ['YYYY-MM-DD', ...]。
 * @throws mysqli_sql_exception 如果数据库操作失败。
 */
function build_calendar_optimized(mysqli $mysqli, string $month, string $year): array
{
    // 准备预处理语句
    $stmt = $mysqli->prepare("SELECT event_date FROM bookings WHERE MONTH(event_date) = ? AND YEAR(event_date)=?");

    // 绑定参数
    // 'ss' 表示两个参数都是字符串类型
    $stmt->bind_param('ss', $month, $year);

    // 执行语句
    $stmt->execute();

    // 获取结果集
    $result = $stmt->get_result();

    // 使用 fetch_all(MYSQLI_ASSOC) 一次性获取所有结果并返回关联数组
    // array_column 用于从结果集中提取 'event_date' 列
    $bookings_data = $result->fetch_all(MYSQLI_ASSOC);

    // 提取 'event_date' 列的值
    return array_column($bookings_data, 'event_date');
}

// 示例调用
try {
    $bookings = build_calendar_optimized($mysqli_connection, '01', '2020');
    print_r($bookings);
} catch (mysqli_sql_exception $e) {
    echo "数据库操作失败: " . $e->getMessage();
    // 记录错误或向用户显示友好信息
} finally {
    // 确保在所有操作完成后关闭连接(如果连接不是持久化的)
    // 在 Web 应用中,PHP 脚本执行结束时通常会自动关闭连接
    // $mysqli_connection->close();
}

在这个优化后的版本中:

  • 通过 mysqli_report() 实现了更强大的错误处理。
  • 函数接收 mysqli 对象作为参数,提高了代码的模块化和可测试性。
  • 使用 fetch_all(MYSQLI_ASSOC) 简化了结果的获取和处理,减少了循环代码。
  • 使用类型提示 (string, array, mysqli) 提高了代码的可读性和健壮性。

总结

尽管 mysqli 提供了面向对象和过程式两种风格,但在现代 PHP 开发中,强烈推荐使用面向对象风格,或更进一步选择 PDO。面向对象风格的 mysqli 提供了更清晰、更现代的 API。通过启用错误报告 (mysqli_report) 和利用 fetch_all 等高级功能,可以编写出更简洁、更健壮、更易于维护的数据库交互代码。避免使用 mysqli_query 处理预处理语句,并始终遵循预处理语句的正确流程:准备、绑定参数、执行、获取结果。

热门AI工具

更多
DeepSeek
DeepSeek

幻方量化公司旗下的开源大模型平台

豆包大模型
豆包大模型

字节跳动自主研发的一系列大型语言模型

WorkBuddy
WorkBuddy

腾讯云推出的AI原生桌面智能体工作台

腾讯元宝
腾讯元宝

腾讯混元平台推出的AI助手

文心一言
文心一言

文心一言是百度开发的AI聊天机器人,通过对话可以生成各种形式的内容。

讯飞写作
讯飞写作

基于讯飞星火大模型的AI写作工具,可以快速生成新闻稿件、品宣文案、工作总结、心得体会等各种文文稿

即梦AI
即梦AI

一站式AI创作平台,免费AI图片和视频生成。

ChatGPT
ChatGPT

最最强大的AI聊天机器人程序,ChatGPT不单是聊天机器人,还能进行撰写邮件、视频脚本、文案、翻译、代码等任务。

相关专题

更多
数据分析工具有哪些
数据分析工具有哪些

数据分析工具有Excel、SQL、Python、R、Tableau、Power BI、SAS、SPSS和MATLAB等。详细介绍:1、Excel,具有强大的计算和数据处理功能;2、SQL,可以进行数据查询、过滤、排序、聚合等操作;3、Python,拥有丰富的数据分析库;4、R,拥有丰富的统计分析库和图形库;5、Tableau,提供了直观易用的用户界面等等。

1134

2023.10.12

SQL中distinct的用法
SQL中distinct的用法

SQL中distinct的语法是“SELECT DISTINCT column1, column2,...,FROM table_name;”。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

340

2023.10.27

SQL中months_between使用方法
SQL中months_between使用方法

在SQL中,MONTHS_BETWEEN 是一个常见的函数,用于计算两个日期之间的月份差。想了解更多SQL的相关内容,可以阅读本专题下面的文章。

381

2024.02.23

SQL出现5120错误解决方法
SQL出现5120错误解决方法

SQL Server错误5120是由于没有足够的权限来访问或操作指定的数据库或文件引起的。想了解更多sql错误的相关内容,可以阅读本专题下面的文章。

2194

2024.03.06

sql procedure语法错误解决方法
sql procedure语法错误解决方法

sql procedure语法错误解决办法:1、仔细检查错误消息;2、检查语法规则;3、检查括号和引号;4、检查变量和参数;5、检查关键字和函数;6、逐步调试;7、参考文档和示例。想了解更多语法错误的相关内容,可以阅读本专题下面的文章。

380

2024.03.06

oracle数据库运行sql方法
oracle数据库运行sql方法

运行sql步骤包括:打开sql plus工具并连接到数据库。在提示符下输入sql语句。按enter键运行该语句。查看结果,错误消息或退出sql plus。想了解更多oracle数据库的相关内容,可以阅读本专题下面的文章。

1703

2024.04.07

sql中where的含义
sql中where的含义

sql中where子句用于从表中过滤数据,它基于指定条件选择特定的行。想了解更多where的相关内容,可以阅读本专题下面的文章。

586

2024.04.29

sql中删除表的语句是什么
sql中删除表的语句是什么

sql中用于删除表的语句是drop table。语法为drop table table_name;该语句将永久删除指定表的表和数据。想了解更多sql的相关内容,可以阅读本专题下面的文章。

440

2024.04.29

TypeScript类型系统进阶与大型前端项目实践
TypeScript类型系统进阶与大型前端项目实践

本专题围绕 TypeScript 在大型前端项目中的应用展开,深入讲解类型系统设计与工程化开发方法。内容包括泛型与高级类型、类型推断机制、声明文件编写、模块化结构设计以及代码规范管理。通过真实项目案例分析,帮助开发者构建类型安全、结构清晰、易维护的前端工程体系,提高团队协作效率与代码质量。

26

2026.03.13

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
MySQL 教程
MySQL 教程

共48课时 | 2.6万人学习

MySQL 初学入门(mosh老师)
MySQL 初学入门(mosh老师)

共3课时 | 0.3万人学习

简单聊聊mysql8与网络通信
简单聊聊mysql8与网络通信

共1课时 | 850人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号