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


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 使用方式。

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

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

$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 的内部机制。以下是将原始面向对象代码转换为过程式风格的示例:

原始面向对象代码:

Copymatic Copymatic

Cowriter是一款AI写作工具,可以通过为你生成内容来帮助你加快写作速度和激发写作灵感。

Copymatic 149 查看详情 Copymatic
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', '2025');
    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 处理预处理语句,并始终遵循预处理语句的正确流程:准备、绑定参数、执行、获取结果。

以上就是PHP mysqli 连接:面向对象与过程式风格解析与优化实践的详细内容,更多请关注php中文网其它相关文章!


# 绑定  # seo联盟壁纸推荐平台  # 律师网站建设及优化  # 银川网站推广蔚鑫hfqjwl下拉  # seo标准词  # 电脑推广qq群的网站  # 新乡实力seo价格  # 朔州网站建设悉云科技  # 搜索类网站推广方案设计  # 汽车配件关键词排名  # 东莞电动车网站建设  # 并将  # 第一个  # mysql  # 两种  # 抛出  # 错误报告  # 已有  # 管理系统  # 转换为  # 面向对象  # yy  # 优化实践  # ai  # php 


相关栏目: 【 Google疑问12 】 【 Facebook疑问10 】 【 优化推广96088 】 【 技术知识133117 】 【 IDC资讯59369 】 【 网络运营7196 】 【 IT资讯61894


相关推荐: 曝《丝之歌》DLC有望开发!开发商还有神秘新企划  VBA Outlook邮件自动化:高效集成Excel数据与列标题的策略  批改网官网首页登录 批改网学生用户登录入口  英雄联盟争者留名活动介绍  PHP中获取HTTP响应状态消息:方法与限制  OPPO A3 WiFi频繁断开怎么办 OPPO A3网络优化技巧  苹果手机聊天记录删除了如何恢复  CSS如何在页面中引入重置样式_使用Normalize.css或Reset.css统一浏览器默认样式  《爱笔思画x》涂色教程  哔哩哔哩的|直播|间怎么送礼物_哔哩哔哩|直播|送礼操作指南  Lar*el Eloquent中通过Join查询关联数据表:解决多行子查询问题  VS Code源代码管理(SCM)视图的进阶使用技巧  《狐友》联系客服方法  qq邮箱格式填写示例 qq邮箱标准填写规范  智学网app怎么登录忘记密码_智学网app忘记密码找回与重新登录操作方法  店铺如何关联视频号推广?视频号推广有什么用?  江苏大剧院会员卡购买步骤  《桃源记2》资源采集攻略  Yandex俄罗斯搜索引擎官网入口 Yandex网页端直接访问  为什么XML解析器对大小写敏感? 理解XML规范中的大小写规则与最佳实践  Flexbox布局中Stencil组件宽度不显示问题解析与:host尺寸控制  邮编号码查询app有哪些_邮编号码查询推荐app及使用体验  包子漫画在线观看入口 包子漫画网正版全集链接  CSS布局中意外顶部空白的调试与解决:深入理解padding-top  CSS过渡如何实现按钮悬停效果_transition属性控制背景颜色变化  泰拉瑞亚网页版在线登录入口 泰拉瑞亚官方正版入口  OPPO手机参数配置如何开启护眼模式_OPPO手机参数配置护眼模式开启指南  Lar*el Dusk 测试中管理浏览器权限:以剪贴板访问为例  嘀嗒顺风车如何开具电子发票  Animex动漫社正版在线入口 Animex动漫社动漫官方观看网  微信注销后银行卡解绑了吗_微信注销后银行卡解绑状态  wps文字怎么设置文字环绕图片的方式_wps文字如何设置文字环绕图片方式  如何在解析前预检查XML文件的完整性? 比如检查文件大小或特定结束标签  J*aScript:从子元素中批量移除特定CSS类  米侠浏览器插件无法启用怎么办 米侠浏览器扩展兼容性修复  Magento 2 产品保存事件中安全更新属性的最佳实践  京东快递包裹信息查询入口 京东快递官方查询平台入口  sublime怎么快速在浏览器中预览HTML_sublime配置View in Browser教程  《海豚家》注销账号方法  《杖剑传说》食谱大全  之了课堂app做题入口  《U校园》学生登录入口2025  PHP页面重载时变量值不重置的实现方法  TikTok笔记文字无法编辑如何解决 TikTok笔记文字编辑优化方法  《爱南宁》认证电动车方法  智慧团建活动报名入口 智慧团建活动报名入口手机端官网​  sublime如何处理超大文件不卡顿 _sublime打开大日志文件技巧  C++ optional用法详解_C++17处理可能为空的返回值  虫虫漫画绿色安全入口_虫虫漫画绿色安全入口安全看漫画  《KARDS》冬季扩展包“国土阵线”上线!全新“协力”机制改变战场格局 

 2025-11-05

了解您产品搜索量及市场趋势,制定营销计划

同行竞争及网站分析保障您的广告效果

点击免费数据支持

提交您的需求,1小时内享受我们的专业解答。

运城市盐湖区信雨科技有限公司


运城市盐湖区信雨科技有限公司

运城市盐湖区信雨科技有限公司是一家深耕海外推广领域十年的专业服务商,作为谷歌推广与Facebook广告全球合作伙伴,聚焦外贸企业出海痛点,以数字化营销为核心,提供一站式海外营销解决方案。公司凭借十年行业沉淀与平台官方资源加持,打破传统外贸获客壁垒,助力企业高效开拓全球市场,成为中小企业出海的可靠合作伙伴。

 8156699

 13765294890

 8156699@qq.com

Notice

We and selected third parties use cookies or similar technologies for technical purposes and, with your consent, for other purposes as specified in the cookie policy.
You can consent to the use of such technologies by closing this notice, by interacting with any link or button outside of this notice or by continuing to browse otherwise.