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