Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/mysql/59.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Php 执行存储过程的模板代码_Php_Mysql_Mysqli - Fatal编程技术网

Php 执行存储过程的模板代码

Php 执行存储过程的模板代码,php,mysql,mysqli,Php,Mysql,Mysqli,通常,当需要通过PHP与MySQL通信时,我会使用类似于以下模板的模板(类似于初学者教程中提供的模板): 尽管到目前为止,该模板工作良好(单服务器),但我的印象是: 下一次查询的准备工作过于复杂(mysqli\u free\u result,mysqli\u more\u results和mysqli\u next\u result) 它不能正确处理错误 问题 对如何改进此模板有何评论或建议?首先,我会给出一个概括的答案,可能会帮助其他人在这个问题上结结巴巴,然后回顾您的具体案例 很久以前

通常,当需要通过PHP与MySQL通信时,我会使用类似于以下模板的模板(类似于初学者教程中提供的模板):

尽管到目前为止,该模板工作良好(单服务器),但我的印象是:

  • 下一次查询的准备工作过于复杂(
    mysqli\u free\u result
    mysqli\u more\u results
    mysqli\u next\u result
  • 它不能正确处理错误

问题


对如何改进此模板有何评论或建议?

首先,我会给出一个概括的答案,可能会帮助其他人在这个问题上结结巴巴,然后回顾您的具体案例

很久以前我也问过自己同样的问题,最终我找到了一套解决方案,使用mysqli简化了数据库操作

Mysqli连接 我对在函数中存储连接代码有疑问。它要求被误用。在单个HTTP请求/php实例期间,应严格地建立一次到单个数据库的连接。但是函数的用途是被多次调用。最好将连接代码放在一个文件中,然后将该文件包含在代码中的一个位置

我有一个在很多问题出现之前就处理过的规范。因此,我们不必使用函数db_connect()而是创建一个名为
mysqli.php
的文件,并将以下代码放在那里

<?php

$host = '127.0.0.1';
$db   = 'test';
$user = 'root';
$pass = '';
$charset = 'utf8mb4';

mysqli_report(MYSQLI_REPORT_ERROR | MYSQLI_REPORT_STRICT);
try {
    $conn = new mysqli($host, $user, $pass, $db);
    $conn->set_charset($charset);
} catch (\mysqli_sql_exception $e) {
     throw new \mysqli_sql_exception($e->getMessage(), $e->getCode());
}
unset($host, $db, $user, $pass, $charset); // we don't need them anymore
您将得到一个工具,它可以使准备好的语句与常规查询一样平滑

使用mysqli调用存储过程 由于一个怪癖,存储过程并不容易:每个调用都会返回多个resultset,因此我们需要对它们进行循环。我们无法避免它,但至少我们也可以使这个过程自动化。我们可以编写一个函数来封装所有结果集jiggery Porky

function prepared_call($mysqli, $sql, $params = [], $types = ""): array
{
    $resource = prepared_query($mysqli, $sql, $params, $types);
    $data = $resource->fetch_all(MYSQLI_ASSOC);
    while(mysqli_more_results($mysqli)) mysqli_next_result($mysqli);
    return $data;
}
用于调用PK的指定函数 最后,我们可以重写您的
select_pk()
函数

function select_pk($mysqli, string $pk): array
{
    $data = prepared_call($mysqli, "CALL select__pk(?)", $pk);
    return $data[0] ?? null;
}   
但我不确定我们是否需要例外:

include 'mysqli.php';

$result = select_pk($mysqli, $pk);
if (!$result) {
    /*** do something ***/
}

你能详细说明一下“不能正确处理错误”吗?这只是一个印象。我的猜测是,我只是没有处理一些重要类型的错误(可能是通信类型的错误?)。但我不确定这些错误会是什么,因此我无法详细阐述比这更好的方法。介意解释一下为什么在
\mysqli\u sql\u exception
中转义吗?与名称空间相关的东西?Typo?>“在其他解决方案中,[
mysqli.php
]会将mysql错误转换为php异常”,考虑到此文件
会引发新异常,是否应该通过标准
require
调用它?还是应该通过
try/catch
语句调用它?>“人们永远不赞成它,因为它是各种人为错误的主题。”请提供一个这样的人为错误示例,即存储过程容易受到攻击,而准备好的语句则不易受攻击?好问题。1.是\是命名空间验证代码。2.始终只是一个标准要求。基本上,只有当您知道在catch块中写什么时,才使用try-catch。3.准备好的语句中的占位符可以100%防止注入,而过程不能。但这是一个太宽泛的话题,无法在评论中讨论。4.无论人们的表现有什么好处,这都是一种错觉。可能是在某种极端情况下,但简单的pk查找肯定不在其中。不知道你的背景,但是在世界上所有的PHP脚本中,有0.0001%使用了proc。剩下的是进一步阅读,尝试catch:,转义/占位符:
function select_pk($mysqli, string $pk): array
{
    $data = prepared_call($mysqli, "CALL select__pk(?)", $pk);
    return $data[0] ?? null;
}   
include 'mysqli.php';

$result = select_pk($mysqli, $pk);
if (!$result) {
    /*** do something ***/
}