自定义mysqli准备功能

时间:2013-02-20 00:47:34

标签: class mysqli prepared-statement sqlbindparameter

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

这个函数的作用是接受一个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是一个数组,如果我记得正确的话,变量需要单独用逗号分隔。这是我无能为力的地方。

1 个答案:

答案 0 :(得分:1)

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

  1. 如果要使用本机预准备语句,请不要将mysqli 用于您自己的第一个数据库类。
    请改用PDO。这将为您节省大量的麻烦。
  2. 尽管这个功能适合你,但它没有多大意义:
    • switch($type)代码块无用。 Mysql可以将每个标量值理解为字符串 - 因此您可以将每个值绑定为 s ,没有任何问题。
    • 来自客户端的大多数整数都有字符串类型。
    • 有一些合法类型,如floatNULL或可返回字符串的对象。因此,自动化在这里不起作用。如果要区分不同的类型,则必须实现类型的暗示占位符
    • 从不在您的脚本中使用exit。而是throw new Exception('put here your error message')
  3. 这实际上不是一个准备函数,因为它也执行。所以,给它更通用的名字
  4. 但是现在你的问题了 这是使用mysqli的直接后果。在处理准备好的陈述时,这是一场噩梦。甚至不仅仅是绑定,而是检索您的数据(因为get_result()不能在任何地方工作,并且在本地创建应用程序后,您会发现它在共享主机上不起作用)。你可以让自己明白为这个目的服务的this bunch of code - 绑定动态数量的变量。

    所以,尽可能远离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);
    

    您可以take a look at my class获得一些想法 随意询问有关数据库类的任何问题 - 这很棒,我很高兴你这样做。

    回答评论中的问题。

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

    带有错误信息的

    exit()做了许多邪恶的事情

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

    当连接到PDO时,不需要在此处抛出任何内容,因为PDO已经抛出了异常。所以,摆脱try ... catch,只留一行:

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

    然后创建一个自定义exception handler以便在两种模式下工作:

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

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

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

    $opt = array( PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION );
    self::$connection = new PDO($dsn, $user, $pass, $opt);