2

我现在正在做我的第一个自己的数据库类,目前我正在做准备功能。

这个函数的作用是接受一个 SQL 查询,然后是一个包含语句变量的数组。我在将参数绑定到语句时遇到问题。

这就是函数现在的样子

public function prepare($query, $var) {
    $types = '';
    foreach($var as $a) {
        $type = gettype($a);
        switch($type) {
            case 'integer':
                $types .= 'i';
                break;

            case 'string':
                $types .= 's';
                break;

            default:
                exit('Invalid type: ' . $a .' ' . $type . '(' . count($a) . ')');
                break;
        }
    }

    $stmt = self::$connection->prepare($query);
    $stmt->bind_param($types, $var); // How do I do here??
    $stmt->execute();
    $result = $stmt->get_result();
    while($row = $result->fetch_assoc()) {
        print_r($row);
    }
}

一切都按我的意愿工作(我知道这个功能可以做一些改进,但它做了它需要做的事情)。我已经评论了我无法弄清楚该怎么做的那一行。$var 是一个数组,如果我没记错的话,变量需要用逗号分开传递。这是我无能为力的地方。

4

1 回答 1

2

您自己的数据库类的想法很棒。
这里很少有人分享它,出于某种原因,他们更喜欢在他们的代码中使用原始 api 调用。
所以,你正在向前迈出一大步。
但是,这里有一些反对意见:

  1. 如果您要使用本机准备好的语句,请不要将 mysqli用于您自己的第一个数据库类。
    请改用 PDO。它将为您节省大量的头痛。
  2. 尽管这个函数对你来说很好用,但它没有多大意义:
    • switch($type)代码块没用。Mysql 可以将每个标量值理解为字符串 - 因此您可以s毫无问题地绑定每个值。
    • 无论如何,来自客户端的大多数整数都有字符串类型。
    • 有一些合法的类型,比如floatorNULL或 object 可以返回一个字符串。所以,自动化在这里行不通。如果要区分不同的类型,则必须改为实现类型提示占位符
    • 永远不要exit在你的脚本中使用。throw new Exception('put here your error message')反而。
  3. 这实际上不是一个准备函数,因为它也执行。所以,给它更通用的名字

但现在你的问题
是使用 mysqli 的直接后果。处理准备好的语句时,这是一场噩梦。不仅可以绑定,还可以检索数据(因为get_result()并非在任何地方都可以使用,并且在本地创建应用程序后,您会发现它在共享主机上不起作用)。您可以通过查看这组为此目的提供的代码来产生想法- 绑定动态数量的变量。

因此,请尽可能远离 mysqli。
使用 PDO,您的功能将像这样简单

public function query($query, $var=array())
{
    $stmt = self::$connection->prepare($query);
    $stmt->execute($var);
    return $stmt->fetchAll(PDO::FETCH_ASSOC);
}
// and then used
$data = $db->("SELECT 1");
print_r($data);

你可以看看我的课来获得一些想法。
随意询问有关数据库类的任何问题 - 这是一件很棒的事情,我很高兴你能走这条路。

回答评论中的问题。

让您知道,您不是该网站的唯一用户。也有一些无辜的游客。与您不同的是,它们不需要任何错误消息,并且会因一些奇怪的行为和缺乏熟悉的控件而感到害怕。

带有错误消息的 exit() 会做很多坏事

  • 抛出一条错误消息,向潜在的攻击者透露一些系统内部信息
  • 用奇怪的信息吓唬无辜的用户。“那是什么?谁是无效的?是我的错还是什么?或者可能是病毒?最好离开网站” - 他们认为。
  • 杀死中间的脚本,因此可能会导致显示设计撕裂(或根本没有设计)
  • 不可恢复地杀死脚本。而抛出的异常可以被捕获并优雅地处理

当连接到 PDO 时,不需要在这里抛出任何东西,因为PDO已经抛出了异常。所以,摆脱try ... catch它,只留下一行:

self::$connection = new PDO($dsn, $user, $pass); 

然后创建一个自定义异常处理程序以在 2 种模式下工作:

  • 在开发服务器上让它在屏幕上抛出消息。
  • 在实时服务器上让它记录错误,同时向用户显示通用错误页面

仅当您不想整个脚本死机时才使用 try ... catch - 即仅处理可恢复的问题。

顺便说一句,PDO 默认情况下不会在连接时抛出异常。您必须手动设置它:

$opt = array( PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION );
self::$connection = new PDO($dsn, $user, $pass, $opt); 
于 2013-02-20T05:01:12.627 回答